1#  Copyright (C) 2024 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# Lint as: python3
16"""Constants for Wifi-Aware Mobly test"""
17
18import enum
19import dataclasses
20import datetime
21import operator
22
23from mobly import utils
24
25# Package name for the Wi-Fi Aware snippet application
26WIFI_AWARE_SNIPPET_PACKAGE_NAME = "com.google.snippet.wifi.aware"
27WIFI_SNIPPET_PACKAGE_NAME = "com.google.snippet.wifi"
28# Timeout duration for Wi-Fi state change operations
29WAIT_WIFI_STATE_TIME_OUT = datetime.timedelta(seconds=30)
30AWARE_NETWORK_INFO_CLASS_NAME = "android.net.wifi.aware.WifiAwareNetworkInfo"
31
32SERVICE_NAME = "service_name"
33SERVICE_SPECIFIC_INFO = "service_specific_info"
34MATCH_FILTER = "match_filter"
35MATCH_FILTER_LIST = "MatchFilterList"
36SUBSCRIBE_TYPE = "subscribe_type"
37PUBLISH_TYPE = "publish_type"
38TERMINATE_NOTIFICATION_ENABLED = "terminate_notification_enabled"
39MAX_DISTANCE_MM = "max_distance_mm"
40PAIRING_CONFIG = "pairing_config"
41AWARE_NETWORK_INFO_CLASS_NAME = "android.net.wifi.aware.WifiAwareNetworkInfo"
42TTL_SEC = "TtlSec"
43INSTANTMODE_ENABLE = "InstantModeEnabled"
44FEATURE_WIFI_AWARE = "feature:android.hardware.wifi.aware"
45
46#onServiceLost reason code
47EASON_PEER_NOT_VISIBLE = 1
48
49class WifiAwareTestConstants:
50    """Constants for Wi-Fi Aware test."""
51    SERVICE_NAME = "CtsVerifierTestService"
52    MATCH_FILTER_BYTES = "bytes used for matching".encode("utf-8")
53    PUB_SSI = "Extra bytes in the publisher discovery".encode("utf-8")
54    SUB_SSI = "Arbitrary bytes for the subscribe discovery".encode("utf-8")
55    LARGE_ENOUGH_DISTANCE_MM = 100000
56    PASSWORD = "Some super secret password"
57    ALIAS_PUBLISH = "publisher"
58    ALIAS_SUBSCRIBE = "subscriber"
59    TEST_WAIT_DURATION_MS = 10000
60    TEST_MESSAGE = "test message!"
61    MESSAGE_ID = 1234
62    MSG_CLIENT_TO_SERVER = 'GET SOME BYTES [Random Identifier: %s]' % utils.rand_ascii_str(5)
63    MSG_SERVER_TO_CLIENT = 'PUT SOME OTHER BYTES [Random Identifier: %s]' % utils.rand_ascii_str(5)
64    PMK = "01234567890123456789012345678901"
65    # 6 == TCP
66    TRANSPORT_PROTOCOL_TCP = 6
67    CHANNEL_IN_MHZ = 5745
68
69
70
71@enum.unique
72class WifiAwareSnippetEventName(enum.StrEnum):
73    """Represents event names for Wi-Fi Aware snippet operations."""
74
75    GET_PAIRED_DEVICE = "getPairedDevices"
76    ON_AVAILABLE = "onAvailable"
77    ON_LOST = "onLost"
78
79
80@enum.unique
81class WifiAwareSnippetParams(enum.StrEnum):
82    """Represents parameters for Wi-Fi Aware snippet events."""
83
84    ALIAS_LIST = "getPairedDevices"
85
86
87@enum.unique
88class DiscoverySessionCallbackMethodType(enum.StrEnum):
89    """Represents the types of callback methods for Wi-Fi Aware discovery sessions.
90
91    These callbacks are correspond to DiscoverySessionCallback in the Android documentation:
92    https://developer.android.com/reference/android/net/wifi/aware/DiscoverySessionCallback
93    """
94
95    PUBLISH_STARTED = "onPublishStarted"
96    SUBSCRIBE_STARTED = "onSubscribeStarted"
97    SESSION_CONFIG_UPDATED = "onSessionConfigUpdated"
98    SESSION_CONFIG_FAILED = "onSessionConfigFailed"
99    SESSION_TERMINATED = "onSessionTerminated"
100    SERVICE_DISCOVERED = "onServiceDiscovered"
101    SERVICE_DISCOVERED_WITHIN_RANGE = "onServiceDiscoveredWithinRange"
102    MESSAGE_SEND_SUCCEEDED = "onMessageSendSucceeded"
103    MESSAGE_SEND_FAILED = "onMessageSendFailed"
104    MESSAGE_RECEIVED = "onMessageReceived"
105    PAIRING_REQUEST_RECEIVED = "onPairingSetupRequestReceived"
106    PAIRING_SETUP_SUCCEEDED = "onPairingSetupSucceeded"
107    PAIRING_SETUP_FAILED = "onPairingSetupFailed"
108    PAIRING_VERIFICATION_SUCCEEDED = "onPairingVerificationSucceed"
109    PAIRING_VERIFICATION_FAILED = "onPairingVerificationFailed"
110    BOOTSTRAPPING_SUCCEEDED = "onBootstrappingSucceeded"
111    BOOTSTRAPPING_FAILED = "onBootstrappingFailed"
112    # Event for the publish or subscribe step: triggered by onPublishStarted or SUBSCRIBE_STARTED or
113    # onSessionConfigFailed
114    DISCOVER_RESULT = "discoveryResult"
115    # Event for the message send result.
116    MESSAGE_SEND_RESULT = "messageSendResult"
117    SESSION_CB_ON_SERVICE_LOST = "WifiAwareSessionOnServiceLost"
118    SESSION_CB_KEY_LOST_REASON = "lostReason"
119
120
121@enum.unique
122class DiscoverySessionCallbackParamsType(enum.StrEnum):
123    CALLBACK_NAME = "callbackName"
124    IS_SESSION_INIT = "isSessionInitialized"
125    MESSAGE_ID = "messageId"
126    RECEIVE_MESSAGE = "receivedMessage"
127
128
129@enum.unique
130class NetworkCbEventName(enum.StrEnum):
131    """Represents the event name for ConnectivityManager network callbacks."""
132    NETWORK_CALLBACK = "NetworkCallback"
133
134
135@enum.unique
136class NetworkCbEventKey(enum.StrEnum):
137    """Represents event data keys for ConnectivityManager network callbacks."""
138    NETWORK = "network"
139    CALLBACK_NAME = "callbackName"
140    NETWORK_CAPABILITIES = "networkCapabilities"
141    TRANSPORT_INFO_CLASS_NAME = "transportInfoClassName"
142    CHANNEL_IN_MHZ = "channelInMhz"
143
144
145@enum.unique
146class NetworkCbName(enum.StrEnum):
147    """Represents the name of network callback for ConnectivityManager.
148
149    These callbacks are correspond to DiscoverySessionCallback in the Android documentation:
150    https://developer.android.com/reference/android/net/ConnectivityManager.NetworkCallback
151    """
152    ON_UNAVAILABLE = "onUnavailable"
153    ON_CAPABILITIES_CHANGED = "onCapabilitiesChanged"
154
155
156@enum.unique
157class RangingResultCb(enum.StrEnum):
158    """Constant for handling callback of snippet RPC wifiAwareStartRanging."""
159
160    # Callback methods related to RangingResultCallback:
161    # https://developer.android.com/reference/android/net/wifi/rtt/RangingResultCallback
162    CB_METHOD_ON_RANGING_RESULT = "onRangingResults"
163    CB_METHOD_ON_RANGING_FAILURE = "onRangingFailure"
164
165    # Other constants related to snippet implementation.
166    EVENT_NAME_ON_RANGING_RESULT = "WifiRttRangingOnRangingResult"
167    DATA_KEY_CALLBACK_NAME = "callbackName"
168    DATA_KEY_RESULTS = 'results'
169    DATA_KEY_RESULT_STATUS = 'status'
170    DATA_KEY_RESULT_DISTANCE_MM = 'distanceMm'
171    DATA_KEY_RESULT_RSSI = 'rssi'
172    DATA_KEY_PEER_ID = 'peerId'
173    DATA_KEY_MAC = 'mac'
174
175
176@enum.unique
177class RangingResultStatusCode(enum.IntEnum):
178  """Ranging result status code.
179
180  This corresponds to status constants in RangingRequest:
181  https://developer.android.com/reference/android/net/wifi/rtt/RangingResult
182  """
183
184  SUCCESS = 0
185  FAIL = 1
186  RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC = 2
187
188
189@enum.unique
190class WifiAwareSnippetParams(enum.StrEnum):
191    """Represents parameters for Wi-Fi Aware snippet events."""
192    SERVICE_SPECIFIC_INFO = "serviceSpecificInfo"
193    RECEIVED_MESSAGE = "receivedMessage"
194    PEER_HANDLE = "peerHandle"
195    MATCH_FILTER = "matchFilter"
196    MATCH_FILTER_VALUE = "value"
197    PAIRING_CONFIG = "pairingConfig"
198    DISTANCE_MM = "distanceMm"
199    LAST_MESSAGE_ID = "lastMessageId"
200    PAIRING_REQUEST_ID = "pairingRequestId"
201    BOOTSTRAPPING_METHOD = "bootstrappingMethod"
202    PEER_ID = "peerId"
203
204
205@enum.unique
206class SubscribeType(enum.IntEnum):
207    """Represents the types of subscriptions in Wi-Fi Aware.
208
209    These callbacks are correspond to SubscribeConfig in the Android documentation:
210    https://developer.android.com/reference/android/net/wifi/aware/SubscribeConfig#constants_1
211    """
212
213    PASSIVE = 0
214    ACTIVE = 1
215
216
217@enum.unique
218class PublishType(enum.IntEnum):
219    """Represents the types of publications in Wi-Fi Aware.
220
221    These publication types are correspond to PublishConfig in the Android documentation:
222    https://developer.android.com/reference/android/net/wifi/aware/PublishConfig#constants_1
223    """
224
225    UNSOLICITED = 0
226    SOLICITED = 1
227
228
229class BootstrappingMethod(enum.IntEnum):
230    """Represents bootstrapping methods for Wi-Fi Aware pairing.
231
232    These types are correspond to AwarePairingConfig bootstrapping methods in the Android
233    documentation:
234    https://developer.android.com/reference/android/net/wifi/aware/AwarePairingConfig#summary
235    """
236    OPPORTUNISTIC = 1
237    PIN_CODE_DISPLAY = 2
238    PASSPHRASE_DISPLAY = 4
239    QR_DISPLAY = 8
240    NFC_TAG = 16
241    PIN_CODE_KEYPAD = 32
242    PASSPHRASE_KEYPAD = 64
243    QR_SCAN = 128
244    NFC_READER = 256
245
246
247@dataclasses.dataclass(frozen=True)
248class AwarePairingConfig:
249    """Config for Wi-Fi Aware Pairing.
250
251    These configurations correspond to AwarePairingConfig in the Android documentation:
252    https://developer.android.com/reference/android/net/wifi/aware/AwarePairingConfig?hl=en
253    """
254    pairing_cache_enabled: bool = False
255    pairing_setup_enabled: bool = False
256    pairing_verification_enabled: bool = False
257    bootstrapping_methods: BootstrappingMethod = BootstrappingMethod.OPPORTUNISTIC
258
259    def to_dict(self) -> dict[str, int | bool]:
260        result = dataclasses.asdict(self)
261        result["bootstrapping_methods"] = self.bootstrapping_methods.value
262        return result
263
264
265@dataclasses.dataclass(frozen=True)
266class SubscribeConfig:
267    """Config for Wi-Fi Aware Subscribe.
268
269    These configurations correspond to SubscribeConfig in the Android documentation:
270    https://developer.android.com/reference/android/net/wifi/aware/SubscribeConfig
271    """
272    subscribe_type: SubscribeType
273    service_specific_info: bytes = WifiAwareTestConstants.SUB_SSI
274    match_filter: list[bytes] | None = (WifiAwareTestConstants.MATCH_FILTER_BYTES, )
275    max_distance_mm: int | None = None
276    pairing_config: AwarePairingConfig | None = None
277    terminate_notification_enabled: bool = True
278    service_name: str = WifiAwareTestConstants.SERVICE_NAME
279
280    def to_dict(self) -> dict[str, str | bool | list[str] | int | dict[str, int | bool | None]]:
281        result = dataclasses.asdict(self)
282        result["subscribe_type"] = self.subscribe_type.value
283        result["service_specific_info"] = self.service_specific_info.decode("utf-8")
284
285        if self.match_filter is None:
286            del result["match_filter"]
287        else:
288            result["match_filter"] = [mf.decode("utf-8") for mf in self.match_filter]
289
290        if self.pairing_config is None:
291            del result["pairing_config"]
292        else:
293            result["pairing_config"] = self.pairing_config.to_dict()
294
295        if self.max_distance_mm is None:
296            del result["max_distance_mm"]
297
298        return result
299
300
301@dataclasses.dataclass(frozen=True)
302class PublishConfig:
303    """Wi-Fi Aware Publish Config.
304
305    These configurations correspond to PublishConfig in the Android documentation:
306    https://developer.android.com/reference/android/net/wifi/aware/PublishConfig
307    """
308    publish_type: PublishType
309    service_specific_info: bytes = WifiAwareTestConstants.PUB_SSI
310    match_filter: list[bytes] | None = (WifiAwareTestConstants.MATCH_FILTER_BYTES, )
311    ranging_enabled: bool = False
312    terminate_notification_enabled: bool = True
313    pairing_config: AwarePairingConfig | None = None
314    service_name: str = WifiAwareTestConstants.SERVICE_NAME
315
316    def to_dict(
317        self,
318    ) -> dict:
319        """Convert PublishConfig to dict."""
320        result = dataclasses.asdict(self)
321        result["publish_type"] = self.publish_type.value
322        result["service_specific_info"] = self.service_specific_info.decode("utf-8")
323        if self.match_filter is None:
324            del result["match_filter"]
325        else:
326            result["match_filter"] = [mf.decode("utf-8") for mf in self.match_filter]
327
328        if self.pairing_config is None:
329            del result["pairing_config"]
330        else:
331            result["pairing_config"] = self.pairing_config.to_dict()
332        return result
333
334
335@dataclasses.dataclass(frozen=True)
336class RangingRequest:
337    """Wi-Fi RTT Ranging request.
338
339    This class correspond to android.net.wifi.rtt.RangingRequest:
340    https://developer.android.com/reference/android/net/wifi/rtt/RangingRequest
341
342    Attributes:
343        peer_ids: A list of peer IDs that will be converted to peer Handles and
344            passed to RangingRequest on device.
345        peer_mac_addresses: A list of peer MAC addresses that will be passed to
346            RangingRequest on device.
347    """
348
349    peer_ids: list[int] = dataclasses.field(default_factory=list)
350    peer_mac_addresses: list[str] = dataclasses.field(default_factory=list)
351
352    def to_dict(self) -> dict:
353        result = {}
354        if self.peer_ids:
355            result['peer_ids'] = self.peer_ids
356        if self.peer_mac_addresses:
357            result['peer_mac_addresses'] = self.peer_mac_addresses
358        return result
359
360
361class NetworkCapabilities:
362    """Network Capabilities.
363
364    https://developer.android.com/reference/android/net/NetworkCapabilities?hl=en#summary
365    """
366
367    class Transport(enum.IntEnum):
368        """Transport type.
369
370        https://developer.android.com/reference/android/net/NetworkCapabilities#TRANSPORT_CELLULAR
371        """
372        TRANSPORT_CELLULAR = 0
373        TRANSPORT_WIFI = 1
374        TRANSPORT_BLUETOOTH = 2
375        TRANSPORT_ETHERNET = 3
376        TRANSPORT_VPN = 4
377        TRANSPORT_WIFI_AWARE = 5
378        TRANSPORT_LOWPAN = 6
379
380    class NetCapability(enum.IntEnum):
381        """Network Capability.
382
383        https://developer.android.com/reference/android/net/NetworkCapabilities#NET_CAPABILITY_MMS
384        """
385        NET_CAPABILITY_MMS = 0
386        NET_CAPABILITY_SUPL = 1
387        NET_CAPABILITY_DUN = 2
388        NET_CAPABILITY_FOTA = 3
389        NET_CAPABILITY_IMS = 4
390        NET_CAPABILITY_CBS = 5
391        NET_CAPABILITY_WIFI_P2P = 6
392        NET_CAPABILITY_IA = 7
393        NET_CAPABILITY_RCS = 8
394        NET_CAPABILITY_XCAP = 9
395        NET_CAPABILITY_EIMS = 10
396        NET_CAPABILITY_NOT_METERED = 11
397        NET_CAPABILITY_INTERNET = 12
398        NET_CAPABILITY_NOT_RESTRICTED = 13
399        NET_CAPABILITY_TRUSTED = 14
400        NET_CAPABILITY_NOT_VPN = 15
401        NET_CAPABILITY_VALIDATED = 16
402        NET_CAPABILITY_CAPTIVE_PORTAL = 17
403        NET_CAPABILITY_NOT_ROAMING = 18
404        NET_CAPABILITY_FOREGROUND = 19
405        NET_CAPABILITY_NOT_CONGESTED = 20
406        NET_CAPABILITY_NOT_SUSPENDED = 21
407        NET_CAPABILITY_OEM_PAID = 22
408        NET_CAPABILITY_MCX = 23
409        NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24
410        NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25
411        NET_CAPABILITY_OEM_PRIVATE = 26
412        NET_CAPABILITY_VEHICLE_INTERNAL = 27
413        NET_CAPABILITY_NOT_VCN_MANAGED = 28
414        NET_CAPABILITY_ENTERPRISE = 29
415        NET_CAPABILITY_VSIM = 30
416        NET_CAPABILITY_BIP = 31
417        NET_CAPABILITY_HEAD_UNIT = 32
418        NET_CAPABILITY_MMTEL = 33
419        NET_CAPABILITY_PRIORITIZE_LATENCY = 34
420        NET_CAPABILITY_PRIORITIZE_BANDWIDTH = 35
421
422
423@dataclasses.dataclass(frozen=True)
424class NetworkRequest:
425    """Wi-Fi Aware Network Request.
426
427    https://developer.android.com/reference/android/net/NetworkRequest
428    """
429    transport_type: NetworkCapabilities.Transport
430    network_specifier_parcel: str
431
432    def to_dict(self) -> dict:
433        result = dataclasses.asdict(self)
434        if not self.network_specifier_parcel:
435            del result["network_specifier_parcel"]
436        if self.transport_type:
437            result["transport_type"] = self.transport_type.value
438        return result
439
440
441class Characteristics(enum.IntEnum):
442    """The characteristics of the Wi-Fi Aware implementation.
443
444    https://developer.android.com/reference/android/net/wifi/aware/Characteristics
445    """
446    WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 = 1
447
448
449@dataclasses.dataclass(frozen=False)
450class WifiAwareDataPathSecurityConfig:
451    """Wi-Fi Aware Network Specifier.
452
453    https://developer.android.com/reference/android/net/wifi/aware/WifiAwareNetworkSpecifier
454    """
455    pmk: str | None = None
456    cipher_suite: Characteristics | None = Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_128
457
458    def to_dict(self) -> dict:
459        result = dataclasses.asdict(self)
460        if not self.pmk:
461            del result["pmk"]
462        if not self.cipher_suite:
463            del result["cipher_suite"]
464        else:
465            result["cipher_suite"] = self.cipher_suite.value
466        return result
467
468
469@dataclasses.dataclass(frozen=False)
470class WifiAwareNetworkSpecifier:
471    """Wi-Fi Aware Network Specifier.
472
473    https://developer.android.com/reference/android/net/wifi/aware/WifiAwareNetworkSpecifier
474    """
475    psk_passphrase: str | None = None
476    port: int | None = None
477    transport_protocol: int | None = None
478    pmk: str | None = None
479    data_path_security_config: WifiAwareDataPathSecurityConfig | None = None
480    channel_frequency_m_hz: int | None = None
481
482    def to_dict(self) -> dict:
483        result = dataclasses.asdict(self)
484        if not self.psk_passphrase:
485            del result["psk_passphrase"]
486        if not self.port:
487            del result["port"]
488        if not self.transport_protocol:
489            del result["transport_protocol"]
490        if not self.pmk:
491            del result["pmk"]
492        if not self.data_path_security_config:
493            del result["data_path_security_config"]
494        else:
495            result["data_path_security_config"] = self.data_path_security_config.to_dict()
496        if not self.channel_frequency_m_hz:
497            del result["channel_frequency_m_hz"]
498        return result
499
500
501class SnippetEventNames:
502    """Represents event names for Wi-Fi Aware snippet operations."""
503
504    SERVER_SOCKET_ACCEPT = "ServerSocketAccept"
505
506
507class SnippetEventParams:
508    """Represents parameters for Wi-Fi Aware snippet events."""
509    IS_ACCEPT = "isAccept"
510    ERROR = "error"
511    LOCAL_PORT = "localPort"
512
513
514@enum.unique
515class AttachCallBackMethodType(enum.StrEnum):
516    """Represents Attach Callback Method Type in Wi-Fi Aware.
517
518    https://developer.android.com/reference/android/net/wifi/aware/AttachCallback
519    """
520    ATTACHED = 'onAttached'
521    ATTACH_FAILED = 'onAttachFailed'
522    AWARE_SESSION_TERMINATED = 'onAwareSessionTerminated'
523    ID_CHANGED = 'WifiAwareAttachOnIdentityChanged'
524
525
526@enum.unique
527class WifiAwareBroadcast(enum.StrEnum):
528    WIFI_AWARE_AVAILABLE = "WifiAwareStateAvailable"
529    WIFI_AWARE_NOT_AVAILABLE = "WifiAwareStateNotAvailable"
530
531
532@enum.unique
533class DeviceidleState(enum.StrEnum):
534    ACTIVE = "ACTIVE"
535    IDLE = "IDLE"
536    INACTIVE = "INACTIVE"
537    OVERRIDE = "OVERRIDE"
538
539
540@enum.unique
541class Operator(enum.Enum):
542    """Operator used in the comparison."""
543
544    GREATER = operator.gt
545    GREATER_EQUAL = operator.ge
546    NOT_EQUAL = operator.ne
547    EQUAL = operator.eq
548    LESS = operator.lt
549    LESS_EQUAL = operator.le
550
551@enum.unique
552class AndroidVersion(enum.IntEnum):
553  """Android OS version."""
554  R = 11
555  S = 12
556  T = 13
557  U = 14
558