1#!/usr/bin/env python3
2#
3#   Copyright 2022 - The Android Open Source Project
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#         http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17from typing import List, NewType, Optional
18
19from acts.controllers.ap_lib.radio_measurement import NeighborReportElement
20
21BssTransitionCandidateList = NewType('BssTransitionCandidateList',
22                                     List[NeighborReportElement])
23
24
25class BssTerminationDuration:
26    """Representation of BSS Termination Duration subelement.
27
28    See IEEE 802.11-2020 Figure 9-341.
29    """
30
31    def __init__(self, duration: int):
32        """Create a BSS Termination Duration subelement.
33
34        Args:
35            duration: number of minutes the BSS will be offline.
36        """
37        # Note: hostapd does not currently support setting BSS Termination TSF,
38        # which is the other value held in this subelement.
39        self._duration = duration
40
41    @property
42    def duration(self) -> int:
43        return self._duration
44
45
46class BssTransitionManagementRequest:
47    """Representation of BSS Transition Management request.
48
49    See IEEE 802.11-2020 9.6.13.9.
50    """
51
52    def __init__(
53            self,
54            preferred_candidate_list_included: bool = False,
55            abridged: bool = False,
56            disassociation_imminent: bool = False,
57            ess_disassociation_imminent: bool = False,
58            disassociation_timer: int = 0,
59            validity_interval: int = 1,
60            bss_termination_duration: Optional[BssTerminationDuration] = None,
61            session_information_url: Optional[str] = None,
62            candidate_list: Optional[BssTransitionCandidateList] = None):
63        """Create a BSS Transition Management request.
64
65        Args:
66            preferred_candidate_list_included: whether the candidate list is a
67                preferred candidate list, or (if False) a list of known
68                candidates.
69            abridged: whether a preference value of 0 is assigned to all BSSIDs
70                that do not appear in the candidate list, or (if False) AP has
71                no recommendation for/against anything not in the candidate
72                list.
73            disassociation_imminent: whether the STA is about to be
74                disassociated by the AP.
75            ess_disassociation_imminent: whether the STA will be disassociated
76                from the ESS.
77            disassociation_timer: the number of beacon transmission times
78                (TBTTs) until the AP disassociates this STA (default 0, meaning
79                AP has not determined when it will disassociate this STA).
80            validity_interval: number of TBTTs until the candidate list is no
81                longer valid (default 1).
82            bss_termination_duration: BSS Termination Duration subelement.
83            session_information_url: this URL is included if ESS disassociation
84                is immiment.
85            candidate_list: zero or more neighbor report elements.
86        """
87        # Request mode field, see IEEE 802.11-2020 Figure 9-924.
88        self._preferred_candidate_list_included = preferred_candidate_list_included
89        self._abridged = abridged
90        self._disassociation_imminent = disassociation_imminent
91        self._ess_disassociation_imminent = ess_disassociation_imminent
92
93        # Disassociation Timer, see IEEE 802.11-2020 Figure 9-925
94        self._disassociation_timer = disassociation_timer
95
96        # Validity Interval, see IEEE 802.11-2020 9.6.13.9
97        self._validity_interval = validity_interval
98
99        # BSS Termination Duration, see IEEE 802.11-2020 9.6.13.9 and Figure 9-341
100        self._bss_termination_duration = bss_termination_duration
101
102        # Session Information URL, see IEEE 802.11-2020 Figure 9-926
103        self._session_information_url = session_information_url
104
105        # BSS Transition Candidate List Entries, IEEE 802.11-2020 9.6.13.9.
106        self._candidate_list = candidate_list
107
108    @property
109    def preferred_candidate_list_included(self) -> bool:
110        return self._preferred_candidate_list_included
111
112    @property
113    def abridged(self) -> bool:
114        return self._abridged
115
116    @property
117    def disassociation_imminent(self) -> bool:
118        return self._disassociation_imminent
119
120    @property
121    def bss_termination_included(self) -> bool:
122        return self._bss_termination_duration is not None
123
124    @property
125    def ess_disassociation_imminent(self) -> bool:
126        return self._ess_disassociation_imminent
127
128    @property
129    def disassociation_timer(self) -> Optional[int]:
130        if self.disassociation_imminent:
131            return self._disassociation_timer
132        # Otherwise, field is reserved.
133        return None
134
135    @property
136    def validity_interval(self) -> int:
137        return self._validity_interval
138
139    @property
140    def bss_termination_duration(self) -> Optional[BssTerminationDuration]:
141        return self._bss_termination_duration
142
143    @property
144    def session_information_url(self) -> Optional[str]:
145        return self._session_information_url
146
147    @property
148    def candidate_list(self) -> Optional[BssTransitionCandidateList]:
149        return self._candidate_list
150