1# Copyright 2019 - 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""" 15Sanity testing for RequestCellInfoUpdate() / GetAllCellInfo() API on Android Q 16and regression check for GetAllCellInfo() on Android P 17""" 18 19import time 20from acts.test_decorators import test_tracker_info 21from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest 22from acts_contrib.test_utils.tel.tel_test_utils import ensure_wifi_connected, \ 23 toggle_airplane_mode, ensure_phones_idle, start_qxdm_loggers 24from acts_contrib.test_utils.wifi import wifi_test_utils 25from acts.utils import disable_usb_charging, enable_usb_charging 26 27NANO_TO_SEC = 1000000000 28RATE_LIMIT_HIGH = 2 29RATE_LIMIT_LOW = 10 30CELL_INFO_UPDATE_WAIT_TIME_HIGH = 10 31CELL_INFO_UPDATE_WAIT_TIME_LOW = 30 32TIME_BETWEEN_CONSECUTIVE_API_CALLS = 0.1 33# wait for 2 sec before start of new test case to account for previous 34# calls to the API by previous test case. 35WAIT_BEFORE_TEST_CASE_START = 2 36WAIT_FOR_CELLULAR_CONNECTION = 20 37 38 39class TelLiveCellInfoTest(TelephonyBaseTest): 40 def setup_class(self): 41 super().setup_class() 42 self.ad = self.android_devices[0] 43 self.wifi_network_ssid = self.user_params.get( 44 "wifi_network_ssid") or self.user_params.get( 45 "wifi_network_ssid_2g") or self.user_params.get( 46 "wifi_network_ssid_5g") 47 self.wifi_network_pass = self.user_params.get( 48 "wifi_network_pass") or self.user_params.get( 49 "wifi_network_pass_2g") or self.user_params.get( 50 "wifi_network_ssid_5g") 51 if self.ad.droid.connectivityCheckAirplaneMode(): 52 toggle_airplane_mode(self.log, self.ad, False) 53 time.sleep(WAIT_FOR_CELLULAR_CONNECTION) 54 55 return True 56 57 def setup_test(self): 58 return True 59 60 def teardown_test(self): 61 return True 62 63 def teardown_class(self): 64 return True 65 66 def time_delta_in_sec(self, time1_ns, time2_ns): 67 """To convert time stamps in nano seconds into seconds and return time 68 delta between the two rounded to 3 digits. 69 70 Args: 71 time1_ns, time2_ns - time stamps in nano seconds 72 73 Returns: 74 delta between the two time stamps in seconds 75 """ 76 sec = round(abs((time1_ns - time2_ns) / NANO_TO_SEC), 3) 77 return sec 78 79 def nano_to_sec(self, nano_time): 80 """ To convert and return time stamp from nano seconds to seconds, 81 rounded to 3 digits. 82 83 Args: 84 nano_time - time in nano seconds 85 86 Returns: 87 time in seconds 88 """ 89 sec = round(nano_time / NANO_TO_SEC, 3) 90 return sec 91 92 def request_cell_info_update_ts(self): 93 """ SL4A API call for RequestCellInfoUpdate() 94 95 Returns: 96 Android system and modem timestamps for 97 RequestCellInfoUpdate() API 98 """ 99 system_ts = self.ad.droid.getSystemElapsedRealtimeNanos() 100 self.log.info("System TS from boot: {}".format(system_ts)) 101 try: 102 request_cell_info_update = \ 103 self.ad.droid.telephonyRequestCellInfoUpdate()[0] 104 except Exception as e: 105 self.log.error( 106 'Failed to read request cell info update from device, please ' 107 'check if device is camped to cellular network.') 108 return False 109 modem_ts = request_cell_info_update['timestamp'] 110 self.log.info("Modem TS from boot: {}".format(modem_ts)) 111 return modem_ts, system_ts 112 113 def _request_cell_info_update(self): 114 time.sleep(WAIT_BEFORE_TEST_CASE_START) 115 try: 116 self.ad.droid.wakeUpNow() 117 modem_ts, system_ts = self.request_cell_info_update_ts() 118 if modem_ts > system_ts: 119 self.log.info("Modem TS exceeds System TS by:{} secs".format( 120 self.time_delta_in_sec(modem_ts, system_ts))) 121 return True 122 else: 123 return False 124 except Exception as e: 125 self.log.error("Exception during request_cell_info_update_ts():" + 126 str(e)) 127 return False 128 129 def get_all_cell_info_ts(self): 130 """SL4A API call for GetAllCellInfo() 131 132 Returns: 133 Android system and modem timestamp for GetAllCellInfo() API 134 """ 135 system_ts = self.ad.droid.getSystemElapsedRealtimeNanos() 136 self.log.info("System TS from boot: {}".format(system_ts)) 137 try: 138 get_all_cell_info = self.ad.droid.telephonyGetAllCellInfo()[0] 139 except Exception as e: 140 self.log.error( 141 'Failed to read get all cell info from device, please ' 142 'check if device is camped to cellular network.') 143 return False 144 modem_ts = get_all_cell_info['timestamp'] 145 self.log.info("Modem TS from boot: {}".format(modem_ts)) 146 return modem_ts, system_ts 147 148 def _get_all_cell_info(self, apk_type): 149 """ 150 Args: 151 apk_type: SL4A APK type - 'Q' for android Q and 'P' for android P 152 153 Returns: 154 Result True if Pass, False if Fail. 155 """ 156 time.sleep(WAIT_BEFORE_TEST_CASE_START) 157 try: 158 self.ad.droid.wakeUpNow() 159 modem_ts, system_ts = self.get_all_cell_info_ts() 160 if apk_type == 'Q': 161 if modem_ts < system_ts: 162 self.log.info( 163 "System TS exceeds Modem TS by:{} secs".format( 164 self.time_delta_in_sec(modem_ts, system_ts))) 165 return True 166 else: 167 return False 168 elif apk_type == 'P': 169 if modem_ts >= system_ts: 170 self.log.info( 171 "Modem TS exceeds System TS by:{} secs".format( 172 self.time_delta_in_sec(modem_ts, system_ts))) 173 return True 174 else: 175 return False 176 except Exception as e: 177 self.log.error("Exception during get_all_cell_info_ts(): " + 178 str(e)) 179 return False 180 181 def request_cell_info_update_rate_limit(self, margin, state): 182 """Get time difference between two cell info updates. 183 184 FOR Q APK: Gets the modem timestamp when RequestCellInfoUpdate() 185 API is called and waits for it to update, and calculates the time 186 delta between the modem timestamp update. 187 188 Args: 189 margin - time in seconds to wait for an updated modem timestamp 190 after calling RequestCellInfoUpdate() 191 state - UE power state (high or low) 192 193 Returns: 194 Time delta between two consecutive unique modem timestamps for 195 margin (sec) corresponding to the UE state as passed in the 196 arguments. 197 False: if the value remains same for margin (sec) passed in method 198 arguments. 199 """ 200 try: 201 ts1 = ts2 = self.ad.droid.telephonyRequestCellInfoUpdate()[0][ 202 'timestamp'] 203 except Exception as e: 204 self.log.error( 205 'Failed to read request cell info update from device, please ' 206 'check if device is camped to cellular network.') 207 return False 208 self.log.info("Modem timestamp: {}".format(ts1)) 209 timeout = time.time() + margin 210 while ts1 == ts2: 211 ts2 = self.ad.droid.telephonyRequestCellInfoUpdate()[0][ 212 'timestamp'] 213 time.sleep(TIME_BETWEEN_CONSECUTIVE_API_CALLS) 214 if time.time() > timeout: 215 self.log.info( 216 "Modem timestamp from RequestCellInfoUpdate() for {} " 217 "powered state " 218 "not refreshed for {} sec".format(state, margin)) 219 return False 220 time_delta = self.nano_to_sec(ts2 - ts1) 221 self.log.info("Updated Modem timestamp: {} in {} sec for " 222 223 "UE in {} powered state".format(ts2, time_delta, state)) 224 return time_delta 225 226 def get_all_cell_info_rate_limit(self, margin, state): 227 """Get time difference between two cell info updates 228 229 FOR P APK: Gets the modem timestamp when GetAllCellInfo() API 230 is called and waits for it to update, and calculates the time delta 231 between the modem timestamp update. 232 233 Args: 234 margin - time in seconds to wait for an updated modem timestamp 235 after calling GetAllCellInfo() 236 state - UE power state (high or low) 237 238 Returns: 239 Time delta between two consecutive unique modem timestamps for 240 margin (sec) corresponding to the UE state as passed in the 241 arguments. 242 False: if the value remains same for margin (sec) passed in 243 method arguments. 244 """ 245 try: 246 ts1 = ts2 = self.ad.droid.telephonyGetAllCellInfo()[0]['timestamp'] 247 except Exception as e: 248 self.log.error( 249 'Failed to read get all cell info from device, please ' 250 'check if device is camped to cellular network.') 251 return False 252 self.log.info("Modem timestamp: {}".format(ts1)) 253 timeout = time.time() + margin 254 while ts1 == ts2: 255 ts2 = self.ad.droid.telephonyGetAllCellInfo()[0]['timestamp'] 256 time.sleep(TIME_BETWEEN_CONSECUTIVE_API_CALLS) 257 if time.time() > timeout: 258 self.log.info( 259 "Modem timestamp from GetAllCellInfo() for {} " 260 "powered state " 261 "not refreshed for {} sec".format(state, margin)) 262 return False 263 time_delta = self.nano_to_sec(ts2 - ts1) 264 self.log.info("Updated Modem timestamp: {} in {} sec for " 265 "UE in {} powered state".format(ts2, time_delta, state)) 266 return time_delta 267 268 def _refresh_get_all_cell_info(self): 269 try: 270 modem_ts1, system_ts1 = self.get_all_cell_info_ts() 271 modem_ts2, system_ts2 = self.request_cell_info_update_ts() 272 modem_ts3, system_ts3 = self.get_all_cell_info_ts() 273 if modem_ts3 > modem_ts1: 274 self.log.info( 275 "Modem TS from GetAllCellInfo() is updated after " 276 "RequestCellInfoUpdate() is called" 277 " by :{} secs".format( 278 self.time_delta_in_sec(modem_ts3, modem_ts1))) 279 return True 280 else: 281 return False 282 except Exception as e: 283 self.log.error("Exception during GetAllCellInfo() Refresh:" + 284 str(e)) 285 return False 286 287 def _power_state_screen_off(self, apk_type): 288 """ 289 Args: 290 apk_type: SL4A APK type - 'Q' for android Q and 'P' for android P 291 292 Returns: 293 Result True if Pass, False if Fail. 294 """ 295 try: 296 self.ad.droid.goToSleepNow() 297 if apk_type == 'Q': 298 time_delta_low = self.request_cell_info_update_rate_limit( 299 CELL_INFO_UPDATE_WAIT_TIME_LOW, 'low') 300 elif apk_type == 'P': 301 time_delta_low = self.get_all_cell_info_rate_limit( 302 CELL_INFO_UPDATE_WAIT_TIME_LOW, 'low') 303 if int(time_delta_low) == RATE_LIMIT_LOW: 304 return True 305 else: 306 return False 307 except Exception as e: 308 self.log.error( 309 "Exception during request_cell_info_update_rate_limit():" + 310 str(e)) 311 return False 312 313 def _power_state_screen_on_wifi_off(self, apk_type): 314 """ 315 Args: 316 apk_type: SL4A APK type - 'Q' for android Q and 'P' for android P 317 318 Returns: 319 Result True if Pass, False if Fail. 320 """ 321 try: 322 self.ad.droid.wakeUpNow() 323 wifi_test_utils.wifi_toggle_state( 324 self.ad, new_state=False, assert_on_fail=True) 325 if apk_type == 'Q': 326 time_delta = self.request_cell_info_update_rate_limit( 327 CELL_INFO_UPDATE_WAIT_TIME_HIGH, 'high') 328 elif apk_type == 'P': 329 time_delta = self.get_all_cell_info_rate_limit( 330 CELL_INFO_UPDATE_WAIT_TIME_HIGH, 'high') 331 if int(time_delta) == RATE_LIMIT_HIGH: 332 return True 333 else: 334 return False 335 except Exception as e: 336 self.log.error( 337 "Exception during request_cell_info_update_rate_limit():" + 338 str(e)) 339 return False 340 341 def _rate_limit_charging_off(self, apk_type): 342 """ 343 Args: 344 apk_type: SL4A APK type - 'Q' for android Q and 'P' for android P 345 346 Returns: 347 Result True if Pass, False if Fail. 348 """ 349 try: 350 self.ad.droid.wakeUpNow() 351 352 if not ensure_wifi_connected(self.log, self.ad, 353 self.wifi_network_ssid, 354 self.wifi_network_pass): 355 self.ad.log.error("Failed to connect to wifi") 356 return False 357 """ Disable Charging """ 358 disable_usb_charging(self.ad) 359 if apk_type == 'P': 360 time_delta = self.get_all_cell_info_rate_limit( 361 CELL_INFO_UPDATE_WAIT_TIME_LOW, 'low') 362 elif apk_type == 'Q': 363 time_delta = self.request_cell_info_update_rate_limit( 364 CELL_INFO_UPDATE_WAIT_TIME_LOW, 'low') 365 """ Enable Charging """ 366 enable_usb_charging(self.ad) 367 if int(time_delta) == RATE_LIMIT_LOW: 368 return True 369 else: 370 return False 371 except Exception as e: 372 self.log.error("Exception in rate_limit function:" + str(e)) 373 return False 374 375 def _rate_limit_switch(self, apk_type): 376 """ 377 Args: 378 apk_type: SL4A APK type - 'Q' for android Q and 'P' for android P 379 380 Returns: 381 Result True if Pass, False if Fail. 382 """ 383 try: 384 pass_count = 0 385 while pass_count != 3: 386 """Put UE in sleep for low powered state""" 387 self.ad.droid.goToSleepNow() 388 if apk_type == 'P': 389 time_delta_low = self.get_all_cell_info_rate_limit( 390 CELL_INFO_UPDATE_WAIT_TIME_LOW, 'low') 391 elif apk_type == 'Q': 392 time_delta_low = self.request_cell_info_update_rate_limit( 393 CELL_INFO_UPDATE_WAIT_TIME_LOW, 'low') 394 if int(time_delta_low) == RATE_LIMIT_LOW: 395 """Wake up UE and turn ON WiFi for high powered state""" 396 self.ad.droid.wakeUpNow() 397 wifi_test_utils.wifi_toggle_state( 398 self.ad, new_state=False, assert_on_fail=True) 399 if apk_type == 'P': 400 time_delta_high = self.get_all_cell_info_rate_limit( 401 CELL_INFO_UPDATE_WAIT_TIME_HIGH, 'high') 402 elif apk_type == 'Q': 403 time_delta_high = \ 404 self.request_cell_info_update_rate_limit( 405 CELL_INFO_UPDATE_WAIT_TIME_HIGH, 'high') 406 if int(time_delta_high) == RATE_LIMIT_HIGH: 407 pass_count += 1 408 else: 409 return False 410 else: 411 return False 412 return True 413 except Exception as e: 414 self.log.error("Exception during rate limit switch:" + str(e)) 415 return False 416 417 """ Tests Start """ 418 """ Q Targeted APK Test Cases """ 419 420 @test_tracker_info(uuid="") 421 @TelephonyBaseTest.tel_test_wrap 422 def test_q_request_cell_info_update(self): 423 """To verify a Q apk receives refreshed info when calling the 424 RequestCellInfoUpdate() API 425 426 Returns: 427 True if pass; False if fail 428 """ 429 return self._request_cell_info_update() 430 431 @test_tracker_info(uuid="") 432 @TelephonyBaseTest.tel_test_wrap 433 def test_q_get_all_cell_info(self): 434 """ To verify a Q apk always receives cached info and never gets 435 refreshed info when calling the GetAllCellInfo() API. 436 437 Returns: 438 True if pass; False if fail 439 """ 440 return self._get_all_cell_info(apk_type='Q') 441 442 @test_tracker_info(uuid="") 443 @TelephonyBaseTest.tel_test_wrap 444 def test_q_get_all_cell_info_refreshed(self): 445 """ To verify in a Q APK the cached info in GetAllCellInfo() is updated 446 after RequestCellInfoUpdate() API provides a refreshed cell info 447 from the modem. 448 449 Returns: 450 True if pass; False if fail 451 """ 452 return self._refresh_get_all_cell_info() 453 454 @test_tracker_info(uuid="") 455 @TelephonyBaseTest.tel_test_wrap 456 def test_q_request_cell_info_update_screen_off(self): 457 """ To verify RATE_LIMIT_LOW is applied when the UE is in low powered 458 state (Screen Off) 459 460 Returns: 461 True if Pass and False if Fail 462 """ 463 return self._power_state_screen_off(apk_type='Q') 464 465 @test_tracker_info(uuid="") 466 @TelephonyBaseTest.tel_test_wrap 467 def test_q_request_cell_info_update_screen_on_wifi_off(self): 468 """ To verify RATE_LIMIT_HIGH is applied when the UE is in high powered 469 state (Screen On / WiFi Off) 470 471 Returns: 472 True if Pass and False if Fail 473 """ 474 return self._power_state_screen_on_wifi_off(apk_type='Q') 475 476 @test_tracker_info(uuid="") 477 @TelephonyBaseTest.tel_test_wrap 478 def test_q_rate_limit_charging_off(self): 479 """ To verify RATE_LIMIT_LOW is applied when the UE is in low powered 480 state (Screen On / WiFi On/Phone NOT charging) 481 482 Returns: 483 True if Pass and False if Fail 484 """ 485 return self._rate_limit_charging_off(apk_type='Q') 486 487 @test_tracker_info(uuid="") 488 @TelephonyBaseTest.tel_test_wrap 489 def test_q_rate_limit_switch(self): 490 """ To verify rate limiting while UE is moving between high-powered & 491 low-powered states for 3 iterations. 492 493 Returns: 494 True if Pass and False if Fail. 495 """ 496 return self._rate_limit_switch(apk_type='Q') 497 498 """ P Targeted APK Test Cases """ 499 500 @test_tracker_info(uuid="") 501 @TelephonyBaseTest.tel_test_wrap 502 def test_p_get_all_cell_info(self): 503 """ To verify a P apk always receives refreshed info when calling the 504 GetAllCellInfo() API 505 506 Returns: 507 True if pass; False if fail 508 """ 509 return self._get_all_cell_info(apk_type='P') 510 511 @test_tracker_info(uuid="") 512 @TelephonyBaseTest.tel_test_wrap 513 def test_p_get_all_cell_info_screen_off(self): 514 """ To verify RATE_LIMIT_LOW is applied when the UE is in low powered 515 state (Screen OFF) 516 517 Returns: 518 True if Pass and False if Fail 519 """ 520 return self._power_state_screen_off(apk_type='P') 521 522 @test_tracker_info(uuid="") 523 @TelephonyBaseTest.tel_test_wrap 524 def test_p_get_all_cell_info_screen_on_wifi_off(self): 525 """ To verify RATE_LIMIT_HIGH is applied when the UE is in high powered 526 state (Screen ON/ WiFi OFF/ Cellular ON) 527 528 Returns: 529 True if Pass and False if Fail 530 """ 531 return self._power_state_screen_on_wifi_off(apk_type='P') 532 533 @test_tracker_info(uuid="") 534 @TelephonyBaseTest.tel_test_wrap 535 def test_p_rate_limit_charging_off(self): 536 """ To verify RATE_LIMIT_LOW is applied when the UE is in low powered 537 state (Screen On / WiFi On/Phone NOT charging) 538 539 Returns: 540 True if Pass and False if Fail 541 """ 542 return self._rate_limit_charging_off(apk_type='P') 543 544 @test_tracker_info(uuid="") 545 @TelephonyBaseTest.tel_test_wrap 546 def test_p_rate_limit_switch(self): 547 """ To verify rate limiting while UE is moving between high-powered & 548 low-powered states. 549 550 Returns: 551 True if Pass and False if Fail. 552 """ 553 return self._rate_limit_switch(apk_type='P') 554 555 """ Tests End """ 556