1#   Copyright 2022 - 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
15from acts.controllers.cellular_lib.BaseSimulation import BaseSimulation
16
17class PresetSimulation(BaseSimulation):
18    """5G preset simulation.
19
20    The simulation will be configed by importing SCPI config file
21    instead of individually set params.
22    """
23
24    # Keys to obtain settings from the test_config dictionary.
25    KEY_CELL_INFO = "cell_info"
26    KEY_SCPI_FILE_NAME = "scpi_file"
27
28    def __init__(self,
29                 simulator,
30                 log,
31                 dut,
32                 test_config,
33                 calibration_table,
34                 nr_mode=None):
35        """Initializes the simulator for 5G preset simulation.
36
37        Args:
38            simulator: a cellular simulator controller.
39            log: a logger handle.
40            dut: a device handler implementing BaseCellularDut.
41            test_config: test configuration obtained from the config file.
42            calibration_table: a dictionary containing path losses
43                for different bands.
44        """
45
46        super().__init__(simulator, log, dut, test_config, calibration_table,
47                         nr_mode)
48        # require param for idle test case
49        self.rrc_sc_timer = 0
50
51        # Set to KeySight APN
52        log.info('Configuring APN.')
53        self.dut.set_apn('Keysight', 'Keysight')
54        self.num_carriers = None
55
56    def setup_simulator(self):
57        """Do initial configuration in the simulator. """
58        self.log.info('This simulation does not require initial setup.')
59
60    def configure(self, parameters):
61        """Configures simulation by importing scpi file.
62
63        A pre-made SCPI file include all the essential configuration
64        for the simulation is imported by send SCPI import command
65        to the callbox.
66
67        Args:
68            parameters: a configuration dictionary which includes scpi file path
69                if there is only one carrier, a list if there are multiple cells.
70        """
71        scpi_file = parameters[0][self.KEY_SCPI_FILE_NAME]
72        cell_infos = parameters[0][self.KEY_CELL_INFO]
73
74        self.log.info('Configure test scenario with\n' +
75                      f' SCPI config file: {scpi_file}\n' +
76                      f' cell info: {cell_infos}')
77
78        self.simulator.import_configuration(scpi_file)
79        self.simulator.set_cell_info(cell_infos)
80
81    def start(self):
82        """Start simulation.
83
84        Waiting for the DUT to connect to the callbox.
85
86        Raise:
87            RuntimeError: simulation fail to start
88                due to unable to connect dut and cells.
89        """
90        self.attach()
91
92    def attach(self):
93        """Attach UE to the callbox.
94
95        Toggle airplane mode on-off and wait for a specified timeout,
96        repeat until the UE connect to the callbox.
97
98        Raise:
99            RuntimeError: attaching fail
100                due to unable to connect dut and cells.
101        """
102        self.simulator.wait_until_attached(self.dut,
103                                           self.attach_timeout,
104                                           self.attach_retries)
105
106    def calibrated_downlink_rx_power(self, bts_config, rsrp):
107        """Convert RSRP to total signal power from the basestation.
108
109        Args:
110            bts_config: the current configuration at the base station
111            rsrp: desired rsrp, contained in a key value pair
112        """
113        raise NotImplementedError(
114            'This simulation mode does not support this configuration option')
115
116    def downlink_calibration(self, rat=None, power_units_conversion_func=None):
117        """Computes downlink path loss and returns the calibration value.
118
119        See base class implementation for details.
120
121        Args:
122            rat: ignored, replaced by 'lteRsrp'.
123            power_units_conversion_func: ignored, replaced by
124                self.rsrp_to_signal_power.
125
126        Returns:
127            Downlink calibration value and measured DL power. Note that the
128            phone only reports RSRP of the primary chain
129        """
130        raise NotImplementedError(
131            'This simulation mode does not support this configuration option')
132
133    def rsrp_to_signal_power(self, rsrp, bts_config):
134        """Converts rsrp to total band signal power
135
136        RSRP is measured per subcarrier, so total band power needs to be
137        multiplied by the number of subcarriers being used.
138
139        Args:
140            rsrp: desired rsrp in dBm.
141            bts_config: a base station configuration object.
142
143        Returns:
144            Total band signal power in dBm
145        """
146        raise NotImplementedError(
147            'This simulation mode does not support this configuration option')
148
149    def maximum_downlink_throughput(self):
150        """Calculates maximum achievable downlink throughput in.
151
152        The calculation is based on the current simulation state
153        Returns:
154            Maximum throughput in mbps.
155        """
156        raise NotImplementedError(
157            'This simulation mode does not support this configuration option')
158
159    def bts_maximum_downlink_throughtput(self, bts_config):
160        """Calculates maximum achievable downlink throughput for a single
161
162        base station from its configuration object.
163
164        Args:
165            bts_config: a base station configuration object.
166
167        Returns:
168            Maximum throughput in mbps.
169        """
170        raise NotImplementedError(
171            'This simulation mode does not support this configuration option')
172
173    def maximum_uplink_throughput(self):
174        """Calculates maximum achievable uplink throughput.
175
176        Returns:
177            Maximum throughput in mbps.
178        """
179        raise NotImplementedError(
180            'This simulation mode does not support this configuration option')
181
182    def bts_maximum_uplink_throughtput(self, bts_config):
183        """Calculates maximum achievable uplink throughput
184
185        The calculation is for selected basestation
186        from its configuration object.
187        Args:
188            bts_config: an LTE base station configuration object.
189
190        Returns:
191            Maximum throughput in mbps.
192
193        """
194        raise NotImplementedError(
195            'This simulation mode does not support this configuration option')
196
197    def calibrate(self, band):
198        """Calculates UL and DL path loss if it wasn't done before
199
200        Before running the base class implementation, configure the base station
201        to only use one downlink antenna with maximum bandwidth.
202
203        Args:
204            band: the band that is currently being calibrated.
205        """
206        raise NotImplementedError(
207            'This simulation mode does not support this configuration option')
208
209    def start_traffic_for_calibration(self):
210        """If MAC padding is enabled, there is no need to start IP traffic. """
211        raise NotImplementedError(
212            'This simulation mode does not support this configuration option')
213
214    def stop_traffic_for_calibration(self):
215        """If MAC padding is enabled, IP traffic wasn't started. """
216        raise NotImplementedError(
217            'This simulation mode does not support this configuration option')
218
219    def get_measured_ul_power(self, samples=5, wait_after_sample=3):
220        """Calculates UL power.
221
222        The calculation is based on measurements from the callbox
223        and the calibration data.
224        Args:
225            samples: the numble of samples to average
226            wait_after_sample: time in seconds to wait in between samples
227
228        Returns:
229            the ul power at the UE antenna ports in dBs
230        """
231        raise NotImplementedError(
232            'This simulation mode does not support this configuration option')
233