1#!/usr/bin/env python3
2#
3#   Copyright 2019 - 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.
16from acts import logger
17from acts.test_utils.power import tel_simulations as sims
18
19
20class AbstractCellularSimulator:
21    """ A generic cellular simulator controller class that can be derived to
22    implement equipment specific classes and allows the tests to be implemented
23    without depending on a singular instrument model.
24
25    This class defines the interface that every cellular simulator controller
26    needs to implement and shouldn't be instantiated by itself. """
27
28    # Indicates if it is able to use 256 QAM as the downlink modulation for LTE
29    LTE_SUPPORTS_DL_256QAM = None
30
31    # Indicates if it is able to use 64 QAM as the uplink modulation for LTE
32    LTE_SUPPORTS_UL_64QAM = None
33
34    # Indicates if 4x4 MIMO is supported for LTE
35    LTE_SUPPORTS_4X4_MIMO = None
36
37    # The maximum number of carriers that this simulator can support for LTE
38    LTE_MAX_CARRIERS = None
39
40    # The maximum power that the equipment is able to transmit
41    MAX_DL_POWER = None
42
43    def __init__(self):
44        """ Initializes the cellular simulator. """
45        self.log = logger.create_tagged_trace_logger('CellularSimulator')
46
47    def destroy(self):
48        """ Sends finalization commands to the cellular equipment and closes
49        the connection. """
50        raise NotImplementedError()
51
52    def setup_lte_scenario(self):
53        """ Configures the equipment for an LTE simulation. """
54        raise NotImplementedError()
55
56    def setup_lte_ca_scenario(self):
57        """ Configures the equipment for an LTE with CA simulation. """
58        raise NotImplementedError()
59
60    def configure_bts(self, config, bts_index=0):
61        """ Commands the equipment to setup a base station with the required
62        configuration. This method applies configurations that are common to all
63        RATs.
64
65        Args:
66            config: a BaseSimulation.BtsConfig object.
67            bts_index: the base station number.
68        """
69
70        if config.output_power:
71            self.set_output_power(bts_index, config.output_power)
72
73        if config.input_power:
74            self.set_input_power(bts_index, config.input_power)
75
76        if isinstance(config, sims.LteSimulation.LteSimulation.BtsConfig):
77            self.configure_lte_bts(config, bts_index)
78
79    def configure_lte_bts(self, config, bts_index=0):
80        """ Commands the equipment to setup an LTE base station with the
81        required configuration.
82
83        Args:
84            config: an LteSimulation.BtsConfig object.
85            bts_index: the base station number.
86        """
87        if config.band:
88            self.set_band(bts_index, config.band)
89
90        if config.dlul_config:
91            self.set_tdd_config(bts_index, config.dlul_config)
92
93        if config.ssf_config:
94            self.set_ssf_config(bts_index, config.ssf_config)
95
96        if config.bandwidth:
97            self.set_bandwidth(bts_index, config.bandwidth)
98
99        if config.dl_channel:
100            self.set_downlink_channel_number(bts_index, config.dl_channel)
101
102        if config.mimo_mode:
103            self.set_mimo_mode(bts_index, config.mimo_mode)
104
105        if config.transmission_mode:
106            self.set_transmission_mode(bts_index, config.transmission_mode)
107
108        # Modulation order should be set before set_scheduling_mode being
109        # called.
110        if config.dl_modulation_order:
111            self.set_dl_modulation(bts_index, config.dl_modulation_order)
112
113        if config.ul_modulation_order:
114            self.set_ul_modulation(bts_index, config.ul_modulation_order)
115
116        if config.scheduling_mode:
117
118            if (config.scheduling_mode ==
119                    sims.LteSimulation.SchedulingMode.STATIC
120                    and not (config.dl_rbs and config.ul_rbs and config.dl_mcs
121                             and config.ul_mcs)):
122                raise ValueError('When the scheduling mode is set to manual, '
123                                 'the RB and MCS parameters are required.')
124
125            # If scheduling mode is set to Dynamic, the RB and MCS parameters
126            # will be ignored by set_scheduling_mode.
127            self.set_scheduling_mode(bts_index, config.scheduling_mode,
128                                     config.dl_mcs, config.ul_mcs,
129                                     config.dl_rbs, config.ul_rbs)
130
131        # This variable stores a boolean value so the following is needed to
132        # differentiate False from None
133        if config.dl_cc_enabled is not None:
134            self.set_enabled_for_ca(bts_index, config.dl_cc_enabled)
135
136        # This variable stores a boolean value so the following is needed to
137        # differentiate False from None
138        if config.tbs_pattern_on is not None:
139            self.set_tbs_pattern_on(bts_index, config.tbs_pattern_on)
140
141        if config.cfi:
142            self.set_cfi(bts_index, config.cfi)
143
144        if config.paging_cycle:
145            self.set_paging_cycle(bts_index, config.paging_cycle)
146
147        if config.phich:
148            self.set_phich_resource(bts_index, config.phich)
149
150    def set_lte_rrc_state_change_timer(self, enabled, time=10):
151        """ Configures the LTE RRC state change timer.
152
153        Args:
154            enabled: a boolean indicating if the timer should be on or off.
155            time: time in seconds for the timer to expire
156        """
157        raise NotImplementedError()
158
159    def set_band(self, bts_index, band):
160        """ Sets the band for the indicated base station.
161
162        Args:
163            bts_index: the base station number
164            band: the new band
165        """
166        raise NotImplementedError()
167
168    def set_input_power(self, bts_index, input_power):
169        """ Sets the input power for the indicated base station.
170
171        Args:
172            bts_index: the base station number
173            input_power: the new input power
174        """
175        raise NotImplementedError()
176
177    def set_output_power(self, bts_index, output_power):
178        """ Sets the output power for the indicated base station.
179
180        Args:
181            bts_index: the base station number
182            output_power: the new output power
183        """
184        raise NotImplementedError()
185
186    def set_tdd_config(self, bts_index, tdd_config):
187        """ Sets the tdd configuration number for the indicated base station.
188
189        Args:
190            bts_index: the base station number
191            tdd_config: the new tdd configuration number
192        """
193        raise NotImplementedError()
194
195    def set_ssf_config(self, bts_index, ssf_config):
196        """ Sets the Special Sub-Frame config number for the indicated
197        base station.
198
199        Args:
200            bts_index: the base station number
201            ssf_config: the new ssf config number
202        """
203        raise NotImplementedError()
204
205    def set_bandwidth(self, bts_index, bandwidth):
206        """ Sets the bandwidth for the indicated base station.
207
208        Args:
209            bts_index: the base station number
210            bandwidth: the new bandwidth
211        """
212        raise NotImplementedError()
213
214    def set_downlink_channel_number(self, bts_index, channel_number):
215        """ Sets the downlink channel number for the indicated base station.
216
217        Args:
218            bts_index: the base station number
219            channel_number: the new channel number
220        """
221        raise NotImplementedError()
222
223    def set_mimo_mode(self, bts_index, mimo_mode):
224        """ Sets the mimo mode for the indicated base station.
225
226        Args:
227            bts_index: the base station number
228            mimo_mode: the new mimo mode
229        """
230        raise NotImplementedError()
231
232    def set_transmission_mode(self, bts_index, transmission_mode):
233        """ Sets the transmission mode for the indicated base station.
234
235        Args:
236            bts_index: the base station number
237            transmission_mode: the new transmission mode
238        """
239        raise NotImplementedError()
240
241    def set_scheduling_mode(self, bts_index, scheduling_mode, mcs_dl, mcs_ul,
242                            nrb_dl, nrb_ul):
243        """ Sets the scheduling mode for the indicated base station.
244
245        Args:
246            bts_index: the base station number
247            scheduling_mode: the new scheduling mode
248            mcs_dl: Downlink MCS (only for STATIC scheduling)
249            mcs_ul: Uplink MCS (only for STATIC scheduling)
250            nrb_dl: Number of RBs for downlink (only for STATIC scheduling)
251            nrb_ul: Number of RBs for uplink (only for STATIC scheduling)
252        """
253        raise NotImplementedError()
254
255    def set_enabled_for_ca(self, bts_index, enabled):
256        """ Enables or disables the base station during carrier aggregation.
257
258        Args:
259            bts_index: the base station number
260            enabled: whether the base station should be enabled for ca.
261        """
262        raise NotImplementedError()
263
264    def set_dl_modulation(self, bts_index, modulation):
265        """ Sets the DL modulation for the indicated base station.
266
267        Args:
268            bts_index: the base station number
269            modulation: the new DL modulation
270        """
271        raise NotImplementedError()
272
273    def set_ul_modulation(self, bts_index, modulation):
274        """ Sets the UL modulation for the indicated base station.
275
276        Args:
277            bts_index: the base station number
278            modulation: the new UL modulation
279        """
280        raise NotImplementedError()
281
282    def set_tbs_pattern_on(self, bts_index, tbs_pattern_on):
283        """ Enables or disables TBS pattern in the indicated base station.
284
285        Args:
286            bts_index: the base station number
287            tbs_pattern_on: the new TBS pattern setting
288        """
289        raise NotImplementedError()
290
291    def set_cfi(self, bts_index, cfi):
292        """ Sets the Channel Format Indicator for the indicated base station.
293
294        Args:
295            bts_index: the base station number
296            cfi: the new CFI setting
297        """
298        raise NotImplementedError()
299
300    def set_paging_cycle(self, bts_index, cycle_duration):
301        """ Sets the paging cycle duration for the indicated base station.
302
303        Args:
304            bts_index: the base station number
305            cycle_duration: the new paging cycle duration in milliseconds
306        """
307        raise NotImplementedError()
308
309    def set_phich_resource(self, bts_index, phich):
310        """ Sets the PHICH Resource setting for the indicated base station.
311
312        Args:
313            bts_index: the base station number
314            phich: the new PHICH resource setting
315        """
316        raise NotImplementedError()
317
318    def lte_attach_secondary_carriers(self):
319        """ Activates the secondary carriers for CA. Requires the DUT to be
320        attached to the primary carrier first. """
321        raise NotImplementedError()
322
323    def wait_until_attached(self, timeout=120):
324        """ Waits until the DUT is attached to the primary carrier.
325
326        Args:
327            timeout: after this amount of time the method will raise a
328                CellularSimulatorError exception. Default is 120 seconds.
329        """
330        raise NotImplementedError()
331
332    def wait_until_communication_state(self, timeout=120):
333        """ Waits until the DUT is in Communication state.
334
335        Args:
336            timeout: after this amount of time the method will raise a
337                CellularSimulatorError exception. Default is 120 seconds.
338        """
339        raise NotImplementedError()
340
341    def wait_until_idle_state(self, timeout=120):
342        """ Waits until the DUT is in Idle state.
343
344        Args:
345            timeout: after this amount of time the method will raise a
346                CellularSimulatorError exception. Default is 120 seconds.
347        """
348        raise NotImplementedError()
349
350    def detach(self):
351        """ Turns off all the base stations so the DUT loose connection."""
352        raise NotImplementedError()
353
354    def stop(self):
355        """ Stops current simulation. After calling this method, the simulator
356        will need to be set up again. """
357        raise NotImplementedError()
358
359    def start_data_traffic(self):
360        """ Starts transmitting data from the instrument to the DUT. """
361        raise NotImplementedError()
362
363    def stop_data_traffic(self):
364        """ Stops transmitting data from the instrument to the DUT. """
365        raise NotImplementedError()
366
367
368class CellularSimulatorError(Exception):
369    """ Exceptions thrown when the cellular equipment is unreachable or it
370    returns an error after receiving a command. """
371    pass
372