1#!/usr/bin/env python3.4 2# 3# Copyright 2016 - Google 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 future import standard_library 18standard_library.install_aliases() 19 20import concurrent.futures 21import urllib.parse 22import time 23 24from queue import Empty 25from acts.controllers.android_device import AndroidDevice 26from acts.controllers.event_dispatcher import EventDispatcher 27from acts.test_utils.tel.tel_defines import AOSP_PREFIX 28from acts.test_utils.tel.tel_defines import CARRIER_UNKNOWN 29from acts.test_utils.tel.tel_defines import DATA_STATE_CONNECTED 30from acts.test_utils.tel.tel_defines import DATA_STATE_DISCONNECTED 31from acts.test_utils.tel.tel_defines import GEN_4G 32from acts.test_utils.tel.tel_defines import GEN_UNKNOWN 33from acts.test_utils.tel.tel_defines import INCALL_UI_DISPLAY_BACKGROUND 34from acts.test_utils.tel.tel_defines import INCALL_UI_DISPLAY_FOREGROUND 35from acts.test_utils.tel.tel_defines import INVALID_SIM_SLOT_INDEX 36from acts.test_utils.tel.tel_defines import INVALID_SUB_ID 37from acts.test_utils.tel.tel_defines import MAX_SAVED_VOICE_MAIL 38from acts.test_utils.tel.tel_defines import MAX_SCREEN_ON_TIME 39from acts.test_utils.tel.tel_defines import \ 40 MAX_WAIT_TIME_ACCEPT_CALL_TO_OFFHOOK_EVENT 41from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_AIRPLANEMODE_EVENT 42from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_CALL_INITIATION 43from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_CALLEE_RINGING 44from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_CONNECTION_STATE_UPDATE 45from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_DATA_SUB_CHANGE 46from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_CALL_IDLE_EVENT 47from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_NW_SELECTION 48from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_SMS_RECEIVE 49from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_SMS_SENT_SUCCESS 50from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_TELECOM_RINGING 51from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_VOICE_MAIL_COUNT 52from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_WFC_DISABLED 53from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_WFC_ENABLED 54from acts.test_utils.tel.tel_defines import NETWORK_MODE_LTE_ONLY 55from acts.test_utils.tel.tel_defines import NETWORK_CONNECTION_TYPE_CELL 56from acts.test_utils.tel.tel_defines import NETWORK_CONNECTION_TYPE_WIFI 57from acts.test_utils.tel.tel_defines import NETWORK_SERVICE_DATA 58from acts.test_utils.tel.tel_defines import NETWORK_SERVICE_VOICE 59from acts.test_utils.tel.tel_defines import PHONE_NUMBER_STRING_FORMAT_7_DIGIT 60from acts.test_utils.tel.tel_defines import PHONE_NUMBER_STRING_FORMAT_10_DIGIT 61from acts.test_utils.tel.tel_defines import PHONE_NUMBER_STRING_FORMAT_11_DIGIT 62from acts.test_utils.tel.tel_defines import PHONE_NUMBER_STRING_FORMAT_12_DIGIT 63from acts.test_utils.tel.tel_defines import RAT_FAMILY_GSM 64from acts.test_utils.tel.tel_defines import RAT_FAMILY_LTE 65from acts.test_utils.tel.tel_defines import RAT_FAMILY_WLAN 66from acts.test_utils.tel.tel_defines import RAT_FAMILY_WCDMA 67from acts.test_utils.tel.tel_defines import RAT_1XRTT 68from acts.test_utils.tel.tel_defines import RAT_UNKNOWN 69from acts.test_utils.tel.tel_defines import SERVICE_STATE_EMERGENCY_ONLY 70from acts.test_utils.tel.tel_defines import SERVICE_STATE_IN_SERVICE 71from acts.test_utils.tel.tel_defines import SERVICE_STATE_OUT_OF_SERVICE 72from acts.test_utils.tel.tel_defines import SERVICE_STATE_POWER_OFF 73from acts.test_utils.tel.tel_defines import SIM_STATE_READY 74from acts.test_utils.tel.tel_defines import TELEPHONY_STATE_IDLE 75from acts.test_utils.tel.tel_defines import TELEPHONY_STATE_OFFHOOK 76from acts.test_utils.tel.tel_defines import TELEPHONY_STATE_RINGING 77from acts.test_utils.tel.tel_defines import VOICEMAIL_DELETE_DIGIT 78from acts.test_utils.tel.tel_defines import WAIT_TIME_1XRTT_VOICE_ATTACH 79from acts.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING 80from acts.test_utils.tel.tel_defines import WAIT_TIME_CHANGE_DATA_SUB_ID 81from acts.test_utils.tel.tel_defines import WAIT_TIME_IN_CALL 82from acts.test_utils.tel.tel_defines import WAIT_TIME_LEAVE_VOICE_MAIL 83from acts.test_utils.tel.tel_defines import WAIT_TIME_REJECT_CALL 84from acts.test_utils.tel.tel_defines import WAIT_TIME_VOICE_MAIL_SERVER_RESPONSE 85from acts.test_utils.tel.tel_defines import WFC_MODE_DISABLED 86from acts.test_utils.tel.tel_defines import EventCallStateChanged 87from acts.test_utils.tel.tel_defines import EventConnectivityChanged 88from acts.test_utils.tel.tel_defines import EventDataConnectionStateChanged 89from acts.test_utils.tel.tel_defines import EventDataSmsReceived 90from acts.test_utils.tel.tel_defines import EventMessageWaitingIndicatorChanged 91from acts.test_utils.tel.tel_defines import EventServiceStateChanged 92from acts.test_utils.tel.tel_defines import EventMmsSentSuccess 93from acts.test_utils.tel.tel_defines import EventSmsReceived 94from acts.test_utils.tel.tel_defines import EventSmsSentSuccess 95from acts.test_utils.tel.tel_defines import CallStateContainer 96from acts.test_utils.tel.tel_defines import DataConnectionStateContainer 97from acts.test_utils.tel.tel_defines import MessageWaitingIndicatorContainer 98from acts.test_utils.tel.tel_defines import NetworkCallbackContainer 99from acts.test_utils.tel.tel_defines import ServiceStateContainer 100from acts.test_utils.tel.tel_lookup_tables import \ 101 connection_type_from_type_string 102from acts.test_utils.tel.tel_lookup_tables import is_valid_rat 103from acts.test_utils.tel.tel_lookup_tables import get_allowable_network_preference 104from acts.test_utils.tel.tel_lookup_tables import \ 105 get_voice_mail_count_check_function 106from acts.test_utils.tel.tel_lookup_tables import get_voice_mail_number_function 107from acts.test_utils.tel.tel_lookup_tables import \ 108 network_preference_for_generaton 109from acts.test_utils.tel.tel_lookup_tables import operator_name_from_plmn_id 110from acts.test_utils.tel.tel_lookup_tables import \ 111 rat_families_for_network_preference 112from acts.test_utils.tel.tel_lookup_tables import rat_family_for_generation 113from acts.test_utils.tel.tel_lookup_tables import rat_family_from_rat 114from acts.test_utils.tel.tel_lookup_tables import rat_generation_from_rat 115from acts.test_utils.tel.tel_subscription_utils import \ 116 get_default_data_sub_id 117from acts.test_utils.tel.tel_subscription_utils import \ 118 get_outgoing_message_sub_id 119from acts.test_utils.tel.tel_subscription_utils import \ 120 get_outgoing_voice_sub_id 121from acts.test_utils.tel.tel_subscription_utils import \ 122 get_incoming_voice_sub_id 123from acts.test_utils.tel.tel_subscription_utils import \ 124 get_incoming_message_sub_id 125from acts.utils import load_config 126from acts.logger import LoggerProxy 127log = LoggerProxy() 128 129 130class TelTestUtilsError(Exception): 131 pass 132 133 134def setup_droid_properties(log, ad, sim_filename): 135 136 # Check to see if droid already has this property 137 if hasattr(ad, 'cfg'): 138 return 139 140 device_props = {} 141 device_props['subscription'] = {} 142 143 try: 144 sim_data = load_config(sim_filename) 145 except Exception: 146 log.warning("Failed to load {}!".format(sim_filename)) 147 sim_data = None 148 sub_info_list = ad.droid.subscriptionGetAllSubInfoList() 149 found_sims = 0 150 for sub_info in sub_info_list: 151 sub_id = sub_info['subscriptionId'] 152 if sub_info['simSlotIndex'] is not INVALID_SIM_SLOT_INDEX: 153 found_sims += 1 154 sim_record = {} 155 try: 156 sim_serial = ad.droid.telephonyGetSimSerialNumberForSubscription( 157 sub_id) 158 if not sim_serial: 159 log.error("Unable to find ICC-ID for SIM on {}!".format( 160 ad.serial)) 161 if sim_data is not None: 162 number = sim_data[sim_serial]["phone_num"] 163 else: 164 raise KeyError("No file to load phone number info!") 165 except KeyError: 166 number = ad.droid.telephonyGetLine1NumberForSubscription( 167 sub_id) 168 if not number or number == "": 169 raise TelTestUtilsError( 170 "Failed to find valid phone number for {}" 171 .format(ad.serial)) 172 173 sim_record['phone_num'] = number 174 sim_record['operator'] = get_operator_name(log, ad, sub_id) 175 device_props['subscription'][sub_id] = sim_record 176 log.info( 177 "phone_info: <{}:{}>, <subId:{}> {} <{}>, ICC-ID:<{}>".format( 178 ad.model, ad.serial, sub_id, number, get_operator_name( 179 log, ad, sub_id), 180 ad.droid.telephonyGetSimSerialNumberForSubscription( 181 sub_id))) 182 183 if found_sims == 0: 184 log.warning("No Valid SIMs found in device {}".format(ad.serial)) 185 186 setattr(ad, 'cfg', device_props) 187 188 189def refresh_droid_config(log, ad): 190 """ Update Android Device cfg records for each sub_id. 191 1. Update Phone Number using Line1Number (if Line1Number is valid). 192 2. Update Operator name. 193 194 Args: 195 log: log object 196 ad: android device object 197 198 Returns: 199 None 200 """ 201 for sub_id in ad.cfg['subscription']: 202 # Update Phone number 203 number = ad.droid.telephonyGetLine1NumberForSubscription(sub_id) 204 if number: 205 number = phone_number_formatter(number) 206 ad.cfg['subscription'][sub_id]['phone_num'] = number 207 # Update Operator Name 208 ad.cfg['subscription'][sub_id]['operator'] = get_operator_name(log, ad, 209 sub_id) 210 211 212def get_slot_index_from_subid(log, ad, sub_id): 213 try: 214 info = ad.droid.subscriptionGetSubInfoForSubscriber(sub_id) 215 return info['simSlotIndex'] 216 except KeyError: 217 return INVALID_SIM_SLOT_INDEX 218 219 220def get_num_active_sims(log, ad): 221 """ Get the number of active SIM cards by counting slots 222 223 Args: 224 ad: android_device object. 225 226 Returns: 227 result: The number of loaded (physical) SIM cards 228 """ 229 # using a dictionary as a cheap way to prevent double counting 230 # in the situation where multiple subscriptions are on the same SIM. 231 # yes, this is a corner corner case. 232 valid_sims = {} 233 subInfo = ad.droid.subscriptionGetAllSubInfoList() 234 for info in subInfo: 235 ssidx = info['simSlotIndex'] 236 if ssidx == INVALID_SIM_SLOT_INDEX: 237 continue 238 valid_sims[ssidx] = True 239 return len(valid_sims.keys()) 240 241 242def toggle_airplane_mode(log, ad, new_state=None): 243 """ Toggle the state of airplane mode. 244 245 Args: 246 ad: android_device object. 247 new_state: Airplane mode state to set to. 248 If None, opposite of the current state. 249 250 Returns: 251 result: True if operation succeed. False if error happens. 252 """ 253 return toggle_airplane_mode_msim(log, ad, new_state) 254 255 256def is_expected_event(event_to_check, events_list): 257 """ check whether event is present in the event list 258 259 Args: 260 event_to_check: event to be checked. 261 events_list: list of events 262 Returns: 263 result: True if event present in the list. False if not. 264 """ 265 for event in events_list: 266 if event in event_to_check['name']: 267 return True 268 return False 269 270 271def is_sim_ready(log, ad, sim_slot_id=None): 272 """ check whether SIM is ready. 273 274 Args: 275 ad: android_device object. 276 sim_slot_id: check the SIM status for sim_slot_id 277 This is optional. If this is None, check default SIM. 278 279 Returns: 280 result: True if all SIMs are ready. False if not. 281 """ 282 if sim_slot_id is None: 283 status = ad.droid.telephonyGetSimState() 284 else: 285 status = ad.droid.telephonyGetSimStateForSlotId(sim_slot_id) 286 if status != SIM_STATE_READY: 287 log.info("Sim not ready") 288 return False 289 return True 290 291 292def _is_expecting_event(event_recv_list): 293 """ check for more event is expected in event list 294 295 Args: 296 event_recv_list: list of events 297 Returns: 298 result: True if more events are expected. False if not. 299 """ 300 for state in event_recv_list: 301 if state is False: 302 return True 303 return False 304 305 306def _set_event_list(event_recv_list, sub_id_list, sub_id, value): 307 """ set received event in expected event list 308 309 Args: 310 event_recv_list: list of received events 311 sub_id_list: subscription ID list 312 sub_id: subscription id of current event 313 value: True or False 314 Returns: 315 None. 316 """ 317 for i in range(len(sub_id_list)): 318 if sub_id_list[i] == sub_id: 319 event_recv_list[i] = value 320 321 322def toggle_airplane_mode_msim(log, ad, new_state=None): 323 """ Toggle the state of airplane mode. 324 325 Args: 326 ad: android_device object. 327 new_state: Airplane mode state to set to. 328 If None, opposite of the current state. 329 330 Returns: 331 result: True if operation succeed. False if error happens. 332 """ 333 serial_number = ad.serial 334 335 ad.ed.clear_all_events() 336 sub_id_list = [] 337 338 active_sub_info = ad.droid.subscriptionGetAllSubInfoList() 339 for info in active_sub_info: 340 sub_id_list.append(info['subscriptionId']) 341 342 cur_state = ad.droid.connectivityCheckAirplaneMode() 343 if cur_state == new_state: 344 log.info("Airplane mode already <{}> on {}".format(new_state, 345 serial_number)) 346 return True 347 elif new_state is None: 348 log.info("Current State {} New state {}".format(cur_state, new_state)) 349 350 if new_state is None: 351 new_state = not cur_state 352 353 service_state_list = [] 354 if new_state: 355 service_state_list.append(SERVICE_STATE_POWER_OFF) 356 log.info("Turn on airplane mode: " + serial_number) 357 358 else: 359 # If either one of these 3 events show up, it should be OK. 360 # Normal SIM, phone in service 361 service_state_list.append(SERVICE_STATE_IN_SERVICE) 362 # NO SIM, or Dead SIM, or no Roaming coverage. 363 service_state_list.append(SERVICE_STATE_OUT_OF_SERVICE) 364 service_state_list.append(SERVICE_STATE_EMERGENCY_ONLY) 365 log.info("Turn off airplane mode: " + serial_number) 366 367 for sub_id in sub_id_list: 368 ad.droid.telephonyStartTrackingServiceStateChangeForSubscription( 369 sub_id) 370 ad.droid.connectivityToggleAirplaneMode(new_state) 371 372 event = None 373 374 try: 375 try: 376 event = ad.ed.wait_for_event( 377 EventServiceStateChanged, 378 is_event_match_for_list, 379 timeout=MAX_WAIT_TIME_AIRPLANEMODE_EVENT, 380 field=ServiceStateContainer.SERVICE_STATE, 381 value_list=service_state_list) 382 except Empty: 383 pass 384 if event is None: 385 log.error("Did not get expected service state {}".format( 386 service_state_list)) 387 log.info("Received event: {}".format(event)) 388 finally: 389 for sub_id in sub_id_list: 390 ad.droid.telephonyStopTrackingServiceStateChangeForSubscription( 391 sub_id) 392 393 if new_state: 394 if (not ad.droid.connectivityCheckAirplaneMode() or 395 ad.droid.wifiCheckState() or ad.droid.bluetoothCheckState()): 396 log.error("Airplane mode ON fail on {}".format(ad.serial)) 397 return False 398 else: 399 if ad.droid.connectivityCheckAirplaneMode(): 400 log.error("Airplane mode OFF fail on {}".format(ad.serial)) 401 return False 402 return True 403 404 405def wait_and_answer_call(log, 406 ad, 407 incoming_number=None, 408 incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND): 409 """Wait for an incoming call on default voice subscription and 410 accepts the call. 411 412 Args: 413 ad: android device object. 414 incoming_number: Expected incoming number. 415 Optional. Default is None 416 incall_ui_display: after answer the call, bring in-call UI to foreground or 417 background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND. 418 if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground. 419 if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background. 420 else, do nothing. 421 422 Returns: 423 True: if incoming call is received and answered successfully. 424 False: for errors 425 """ 426 return wait_and_answer_call_for_subscription( 427 log, ad, get_incoming_voice_sub_id(ad), incoming_number, 428 incall_ui_display) 429 430 431def wait_for_ringing_event(log, ad, wait_time): 432 """Wait for ringing event. 433 434 Args: 435 log: log object. 436 ad: android device object. 437 wait_time: max time to wait for ringing event. 438 439 Returns: 440 event_ringing if received ringing event. 441 otherwise return None. 442 """ 443 log.info("Wait for ringing.") 444 start_time = time.time() 445 remaining_time = wait_time 446 event_iter_timeout = 4 447 event_ringing = None 448 449 while remaining_time > 0: 450 try: 451 event_ringing = ad.ed.wait_for_event( 452 EventCallStateChanged, 453 is_event_match, 454 timeout=event_iter_timeout, 455 field=CallStateContainer.CALL_STATE, 456 value=TELEPHONY_STATE_RINGING) 457 except Empty: 458 if ad.droid.telecomIsRinging(): 459 log.error("No Ringing event. But Callee in Ringing state.") 460 log.error("Test framework dropped event.") 461 return None 462 remaining_time = start_time + wait_time - time.time() 463 if event_ringing is not None: 464 break 465 if event_ringing is None: 466 log.error("No Ringing Event, Callee not in ringing state.") 467 log.error("No incoming call.") 468 return None 469 470 return event_ringing 471 472 473def wait_and_answer_call_for_subscription( 474 log, 475 ad, 476 sub_id, 477 incoming_number=None, 478 incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND): 479 """Wait for an incoming call on specified subscription and 480 accepts the call. 481 482 Args: 483 ad: android device object. 484 sub_id: subscription ID 485 incoming_number: Expected incoming number. 486 Optional. Default is None 487 incall_ui_display: after answer the call, bring in-call UI to foreground or 488 background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND. 489 if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground. 490 if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background. 491 else, do nothing. 492 493 Returns: 494 True: if incoming call is received and answered successfully. 495 False: for errors 496 """ 497 ad.ed.clear_all_events() 498 ad.droid.telephonyStartTrackingCallStateForSubscription(sub_id) 499 if (not ad.droid.telecomIsRinging() and 500 ad.droid.telephonyGetCallStateForSubscription(sub_id) != 501 TELEPHONY_STATE_RINGING): 502 try: 503 event_ringing = wait_for_ringing_event( 504 log, ad, MAX_WAIT_TIME_CALLEE_RINGING) 505 if event_ringing is None: 506 log.error("No Ringing Event.") 507 return False 508 finally: 509 ad.droid.telephonyStopTrackingCallStateChangeForSubscription( 510 sub_id) 511 512 if not incoming_number: 513 result = True 514 else: 515 result = check_phone_number_match( 516 event_ringing['data'][CallStateContainer.INCOMING_NUMBER], 517 incoming_number) 518 519 if not result: 520 log.error("Incoming Number not match") 521 log.error("Expected number:{}, actual number:{}".format( 522 incoming_number, event_ringing['data'][ 523 CallStateContainer.INCOMING_NUMBER])) 524 return False 525 526 ad.ed.clear_all_events() 527 ad.droid.telephonyStartTrackingCallStateForSubscription(sub_id) 528 if not wait_for_telecom_ringing(log, ad, MAX_WAIT_TIME_TELECOM_RINGING): 529 log.error("Telecom is not ringing.") 530 return False 531 log.info("Accept on callee.") 532 ad.droid.telecomAcceptRingingCall() 533 try: 534 ad.ed.wait_for_event( 535 EventCallStateChanged, 536 is_event_match, 537 timeout=MAX_WAIT_TIME_ACCEPT_CALL_TO_OFFHOOK_EVENT, 538 field=CallStateContainer.CALL_STATE, 539 value=TELEPHONY_STATE_OFFHOOK) 540 except Empty: 541 if not ad.droid.telecomIsInCall(): 542 log.error("Accept call failed.") 543 return False 544 finally: 545 ad.droid.telephonyStopTrackingCallStateChangeForSubscription(sub_id) 546 if incall_ui_display == INCALL_UI_DISPLAY_FOREGROUND: 547 ad.droid.telecomShowInCallScreen() 548 elif incall_ui_display == INCALL_UI_DISPLAY_BACKGROUND: 549 ad.droid.showHomeScreen() 550 return True 551 552 553def wait_and_reject_call(log, 554 ad, 555 incoming_number=None, 556 delay_reject=WAIT_TIME_REJECT_CALL, 557 reject=True): 558 """Wait for an incoming call on default voice subscription and 559 reject the call. 560 561 Args: 562 ad: android device object. 563 incoming_number: Expected incoming number. 564 Optional. Default is None 565 delay_reject: time to wait before rejecting the call 566 Optional. Default is WAIT_TIME_REJECT_CALL 567 568 Returns: 569 True: if incoming call is received and reject successfully. 570 False: for errors 571 """ 572 return wait_and_reject_call_for_subscription( 573 log, ad, get_incoming_voice_sub_id(ad), incoming_number, delay_reject, 574 reject) 575 576 577def wait_and_reject_call_for_subscription(log, 578 ad, 579 sub_id, 580 incoming_number=None, 581 delay_reject=WAIT_TIME_REJECT_CALL, 582 reject=True): 583 """Wait for an incoming call on specific subscription and 584 reject the call. 585 586 Args: 587 ad: android device object. 588 sub_id: subscription ID 589 incoming_number: Expected incoming number. 590 Optional. Default is None 591 delay_reject: time to wait before rejecting the call 592 Optional. Default is WAIT_TIME_REJECT_CALL 593 594 Returns: 595 True: if incoming call is received and reject successfully. 596 False: for errors 597 """ 598 ad.ed.clear_all_events() 599 ad.droid.telephonyStartTrackingCallStateForSubscription(sub_id) 600 if (not ad.droid.telecomIsRinging() and 601 ad.droid.telephonyGetCallStateForSubscription(sub_id) != 602 TELEPHONY_STATE_RINGING): 603 try: 604 event_ringing = wait_for_ringing_event( 605 log, ad, MAX_WAIT_TIME_CALLEE_RINGING) 606 if event_ringing is None: 607 log.error("No Ringing Event.") 608 return False 609 finally: 610 ad.droid.telephonyStopTrackingCallStateChangeForSubscription( 611 sub_id) 612 613 if not incoming_number: 614 result = True 615 else: 616 result = check_phone_number_match( 617 event_ringing['data'][CallStateContainer.INCOMING_NUMBER], 618 incoming_number) 619 620 if not result: 621 log.error("Incoming Number not match") 622 log.error("Expected number:{}, actual number:{}".format( 623 incoming_number, event_ringing['data'][ 624 CallStateContainer.INCOMING_NUMBER])) 625 return False 626 627 ad.ed.clear_all_events() 628 ad.droid.telephonyStartTrackingCallStateForSubscription(sub_id) 629 if reject is True: 630 # Delay between ringing and reject. 631 time.sleep(delay_reject) 632 log.info("Reject on callee.") 633 is_find = False 634 # Loop the call list and find the matched one to disconnect. 635 for call in ad.droid.telecomCallGetCallIds(): 636 if check_phone_number_match( 637 get_number_from_tel_uri(get_call_uri(ad, call)), 638 incoming_number): 639 ad.droid.telecomCallDisconnect(call) 640 is_find = True 641 if is_find is False: 642 log.error("Did not find matching call to reject.") 643 return False 644 else: 645 # don't reject on callee. Just ignore the incoming call. 646 log.info("Received incoming call. Ignore it.") 647 try: 648 ad.ed.wait_for_event( 649 EventCallStateChanged, 650 is_event_match_for_list, 651 timeout=MAX_WAIT_TIME_CALL_IDLE_EVENT, 652 field=CallStateContainer.CALL_STATE, 653 value_list=[TELEPHONY_STATE_IDLE, TELEPHONY_STATE_OFFHOOK]) 654 except Empty: 655 log.error("No onCallStateChangedIdle event received.") 656 return False 657 finally: 658 ad.droid.telephonyStopTrackingCallStateChangeForSubscription(sub_id) 659 return True 660 661 662def hangup_call(log, ad): 663 """Hang up ongoing active call. 664 """ 665 ad.ed.clear_all_events() 666 ad.droid.telephonyStartTrackingCallState() 667 log.info("Hangup call.") 668 ad.droid.telecomEndCall() 669 670 try: 671 ad.ed.wait_for_event(EventCallStateChanged, 672 is_event_match, 673 timeout=MAX_WAIT_TIME_CALL_IDLE_EVENT, 674 field=CallStateContainer.CALL_STATE, 675 value=TELEPHONY_STATE_IDLE) 676 except Empty: 677 if ad.droid.telecomIsInCall(): 678 log.error("Hangup call failed.") 679 return False 680 finally: 681 ad.droid.telephonyStopTrackingCallStateChange() 682 return True 683 684 685def disconnect_call_by_id(log, ad, call_id): 686 """Disconnect call by call id. 687 """ 688 ad.droid.telecomCallDisconnect(call_id) 689 return True 690 691def _phone_number_remove_prefix(number): 692 """Remove the country code and other prefix from the input phone number. 693 Currently only handle phone number with the following formats: 694 (US phone number format) 695 +1abcxxxyyyy 696 1abcxxxyyyy 697 abcxxxyyyy 698 abc xxx yyyy 699 abc.xxx.yyyy 700 abc-xxx-yyyy 701 (EEUK phone number format) 702 +44abcxxxyyyy 703 0abcxxxyyyy 704 705 Args: 706 number: input phone number 707 708 Returns: 709 Phone number without country code or prefix 710 """ 711 if number is None: 712 return None, None 713 country_code_list = ["+1", "+44"] 714 for country_code in country_code_list: 715 if number.startswith(country_code): 716 return number[len(country_code):], country_code 717 if number[0] == "1" or number[0] == "0": 718 return number[1:], None 719 return number, None 720 721 722def check_phone_number_match(number1, number2): 723 """Check whether two input phone numbers match or not. 724 725 Compare the two input phone numbers. 726 If they match, return True; otherwise, return False. 727 Currently only handle phone number with the following formats: 728 (US phone number format) 729 +1abcxxxyyyy 730 1abcxxxyyyy 731 abcxxxyyyy 732 abc xxx yyyy 733 abc.xxx.yyyy 734 abc-xxx-yyyy 735 (EEUK phone number format) 736 +44abcxxxyyyy 737 0abcxxxyyyy 738 739 There are some scenarios we can not verify, one example is: 740 number1 = +15555555555, number2 = 5555555555 741 (number2 have no country code) 742 743 Args: 744 number1: 1st phone number to be compared. 745 number2: 2nd phone number to be compared. 746 747 Returns: 748 True if two phone numbers match. Otherwise False. 749 """ 750 # Remove country code and prefix 751 number1, country_code1 = _phone_number_remove_prefix(number1) 752 number2, country_code2 = _phone_number_remove_prefix(number2) 753 if ((country_code1 is not None) and 754 (country_code2 is not None) and 755 (country_code1 != country_code2)): 756 return False 757 # Remove white spaces, dashes, dots 758 number1 = phone_number_formatter(number1) 759 number2 = phone_number_formatter(number2) 760 return number1 == number2 761 762 763def initiate_call(log, ad_caller, callee_number, emergency=False): 764 """Make phone call from caller to callee. 765 766 Args: 767 ad_caller: Caller android device object. 768 callee_number: Callee phone number. 769 emergency : specify the call is emergency. 770 Optional. Default value is False. 771 772 Returns: 773 result: if phone call is placed successfully. 774 """ 775 ad_caller.ed.clear_all_events() 776 sub_id = get_outgoing_voice_sub_id(ad_caller) 777 ad_caller.droid.telephonyStartTrackingCallStateForSubscription(sub_id) 778 779 wait_time_for_incall_state = MAX_WAIT_TIME_CALL_INITIATION 780 781 try: 782 # Make a Call 783 if emergency: 784 ad_caller.droid.telecomCallEmergencyNumber(callee_number) 785 else: 786 ad_caller.droid.telecomCallNumber(callee_number) 787 788 # Verify OFFHOOK event 789 if ad_caller.droid.telephonyGetCallState() != TELEPHONY_STATE_OFFHOOK: 790 event_offhook = ad_caller.ed.wait_for_event( 791 EventCallStateChanged, 792 is_event_match, 793 timeout=wait_time_for_incall_state, 794 field=CallStateContainer.CALL_STATE, 795 value=TELEPHONY_STATE_OFFHOOK) 796 except Empty: 797 log.error("initiate_call did not receive Telephony OFFHOOK event.") 798 return False 799 finally: 800 ad_caller.droid.telephonyStopTrackingCallStateChangeForSubscription( 801 sub_id) 802 803 # Verify call state 804 while wait_time_for_incall_state > 0: 805 wait_time_for_incall_state -= 1 806 if (ad_caller.droid.telecomIsInCall() and 807 (ad_caller.droid.telephonyGetCallState() == 808 TELEPHONY_STATE_OFFHOOK) and 809 (ad_caller.droid.telecomGetCallState() == 810 TELEPHONY_STATE_OFFHOOK)): 811 return True 812 time.sleep(1) 813 log.error("Make call fail. telecomIsInCall:{}, Telecom State:{}," 814 " Telephony State:{}".format(ad_caller.droid.telecomIsInCall( 815 ), ad_caller.droid.telephonyGetCallState( 816 ), ad_caller.droid.telecomGetCallState())) 817 return False 818 819 820def call_reject(log, ad_caller, ad_callee, reject=True): 821 """Caller call Callee, then reject on callee. 822 823 824 """ 825 subid_caller = ad_caller.droid.subscriptionGetDefaultVoiceSubId() 826 subid_callee = ad_callee.incoming_voice_sub_id 827 log.info("Sub-ID Caller {}, Sub-ID Callee {}".format(subid_caller, 828 subid_callee)) 829 return call_reject_for_subscription(log, ad_caller, ad_callee, 830 subid_caller, subid_callee, reject) 831 832 833def call_reject_for_subscription(log, 834 ad_caller, 835 ad_callee, 836 subid_caller, 837 subid_callee, 838 reject=True): 839 """ 840 """ 841 842 class _CallSequenceException(Exception): 843 pass 844 845 caller_number = ad_caller.cfg['subscription'][subid_caller]['phone_num'] 846 callee_number = ad_callee.cfg['subscription'][subid_callee]['phone_num'] 847 848 log.info("Call from {} to {}".format(caller_number, callee_number)) 849 try: 850 if not initiate_call(log, ad_caller, callee_number): 851 raise _CallSequenceException("Initiate call failed.") 852 853 if not wait_and_reject_call_for_subscription( 854 log, ad_callee, subid_callee, caller_number, 855 WAIT_TIME_REJECT_CALL, reject): 856 raise _CallSequenceException("Reject call fail.") 857 # Check if incoming call is cleared on callee or not. 858 if ad_callee.droid.telephonyGetCallStateForSubscription( 859 subid_callee) == TELEPHONY_STATE_RINGING: 860 raise _CallSequenceException("Incoming call is not cleared.") 861 # Hangup on caller 862 hangup_call(log, ad_caller) 863 except _CallSequenceException as e: 864 log.error(e) 865 return False 866 return True 867 868 869def call_reject_leave_message(log, 870 ad_caller, 871 ad_callee, 872 verify_caller_func=None, 873 wait_time_in_call=WAIT_TIME_LEAVE_VOICE_MAIL): 874 """On default voice subscription, Call from caller to callee, 875 reject on callee, caller leave a voice mail. 876 877 1. Caller call Callee. 878 2. Callee reject incoming call. 879 3. Caller leave a voice mail. 880 4. Verify callee received the voice mail notification. 881 882 Args: 883 ad_caller: caller android device object. 884 ad_callee: callee android device object. 885 verify_caller_func: function to verify caller is in correct state while in-call. 886 This is optional, default is None. 887 wait_time_in_call: time to wait when leaving a voice mail. 888 This is optional, default is WAIT_TIME_LEAVE_VOICE_MAIL 889 890 Returns: 891 True: if voice message is received on callee successfully. 892 False: for errors 893 """ 894 subid_caller = get_outgoing_voice_sub_id(ad_caller) 895 subid_callee = get_incoming_voice_sub_id(ad_callee) 896 return call_reject_leave_message_for_subscription( 897 log, ad_caller, ad_callee, subid_caller, subid_callee, 898 verify_caller_func, wait_time_in_call) 899 900 901def call_reject_leave_message_for_subscription( 902 log, 903 ad_caller, 904 ad_callee, 905 subid_caller, 906 subid_callee, 907 verify_caller_func=None, 908 wait_time_in_call=WAIT_TIME_LEAVE_VOICE_MAIL): 909 """On specific voice subscription, Call from caller to callee, 910 reject on callee, caller leave a voice mail. 911 912 1. Caller call Callee. 913 2. Callee reject incoming call. 914 3. Caller leave a voice mail. 915 4. Verify callee received the voice mail notification. 916 917 Args: 918 ad_caller: caller android device object. 919 ad_callee: callee android device object. 920 subid_caller: caller's subscription id. 921 subid_callee: callee's subscription id. 922 verify_caller_func: function to verify caller is in correct state while in-call. 923 This is optional, default is None. 924 wait_time_in_call: time to wait when leaving a voice mail. 925 This is optional, default is WAIT_TIME_LEAVE_VOICE_MAIL 926 927 Returns: 928 True: if voice message is received on callee successfully. 929 False: for errors 930 """ 931 932 class _CallSequenceException(Exception): 933 pass 934 # Currently this test utility only works for TMO and ATT and SPT. 935 # It does not work for VZW (see b/21559800) 936 # "with VVM TelephonyManager APIs won't work for vm" 937 938 caller_number = ad_caller.cfg['subscription'][subid_caller]['phone_num'] 939 callee_number = ad_callee.cfg['subscription'][subid_callee]['phone_num'] 940 941 log.info("Call from {} to {}".format(caller_number, callee_number)) 942 943 try: 944 945 if not initiate_call(log, ad_caller, callee_number): 946 raise _CallSequenceException("Initiate call failed.") 947 948 if not wait_and_reject_call_for_subscription( 949 log, 950 ad_callee, 951 subid_callee, 952 incoming_number=caller_number): 953 raise _CallSequenceException("Reject call fail.") 954 955 ad_callee.droid.telephonyStartTrackingVoiceMailStateChangeForSubscription( 956 subid_callee) 957 voice_mail_count_before = ad_callee.droid.telephonyGetVoiceMailCountForSubscription( 958 subid_callee) 959 960 # -1 means there are unread voice mail, but the count is unknown 961 # 0 means either this API not working (VZW) or no unread voice mail. 962 if voice_mail_count_before != 0: 963 log.warning("--Pending new Voice Mail, please clear on phone.--") 964 965 # ensure that all internal states are updated in telecom 966 time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) 967 ad_callee.ed.clear_all_events() 968 969 if verify_caller_func and not verify_caller_func(log, ad_caller): 970 raise _CallSequenceException("Caller not in correct state!") 971 972 # TODO: b/26293512 Need to play some sound to leave message. 973 # Otherwise carrier voice mail server may drop this voice mail. 974 975 time.sleep(wait_time_in_call) 976 977 if not verify_caller_func: 978 caller_state_result = ad_caller.droid.telecomIsInCall() 979 else: 980 caller_state_result = verify_caller_func(log, ad_caller) 981 if not caller_state_result: 982 raise _CallSequenceException( 983 "Caller not in correct state after {} seconds".format( 984 wait_time_in_call)) 985 986 if not hangup_call(log, ad_caller): 987 raise _CallSequenceException("Error in Hanging-Up Call") 988 989 log.info("Wait for voice mail indicator on callee.") 990 try: 991 event = ad_callee.ed.wait_for_event( 992 EventMessageWaitingIndicatorChanged, 993 _is_on_message_waiting_event_true) 994 log.info(event) 995 except Empty: 996 raise _CallSequenceException("No expected event {}.".format( 997 EventMessageWaitingIndicatorChanged)) 998 voice_mail_count_after = ad_callee.droid.telephonyGetVoiceMailCountForSubscription( 999 subid_callee) 1000 log.info( 1001 "telephonyGetVoiceMailCount output - before: {}, after: {}".format( 1002 voice_mail_count_before, voice_mail_count_after)) 1003 1004 # voice_mail_count_after should: 1005 # either equals to (voice_mail_count_before + 1) [For ATT and SPT] 1006 # or equals to -1 [For TMO] 1007 # -1 means there are unread voice mail, but the count is unknown 1008 if not check_voice_mail_count(log, ad_callee, voice_mail_count_before, 1009 voice_mail_count_after): 1010 log.error("telephonyGetVoiceMailCount output is incorrect.") 1011 return False 1012 1013 except _CallSequenceException as e: 1014 log.error(e) 1015 return False 1016 finally: 1017 ad_callee.droid.telephonyStopTrackingVoiceMailStateChangeForSubscription( 1018 subid_callee) 1019 return True 1020 1021 1022def call_voicemail_erase_all_pending_voicemail(log, ad): 1023 """Script for phone to erase all pending voice mail. 1024 This script only works for TMO and ATT and SPT currently. 1025 This script only works if phone have already set up voice mail options, 1026 and phone should disable password protection for voice mail. 1027 1028 1. If phone don't have pending voice message, return True. 1029 2. Dial voice mail number. 1030 For TMO, the number is '123' 1031 For ATT, the number is phone's number 1032 For SPT, the number is phone's number 1033 3. Wait for voice mail connection setup. 1034 4. Wait for voice mail play pending voice message. 1035 5. Send DTMF to delete one message. 1036 The digit is '7'. 1037 6. Repeat steps 4 and 5 until voice mail server drop this call. 1038 (No pending message) 1039 6. Check telephonyGetVoiceMailCount result. it should be 0. 1040 1041 Args: 1042 log: log object 1043 ad: android device object 1044 Returns: 1045 False if error happens. True is succeed. 1046 """ 1047 log.info("Erase all pending voice mail.") 1048 if ad.droid.telephonyGetVoiceMailCount() == 0: 1049 log.info("No Pending voice mail.") 1050 return True 1051 1052 voice_mail_number = get_voice_mail_number(log, ad) 1053 1054 if not initiate_call(log, ad, voice_mail_number): 1055 log.error("Initiate call failed.") 1056 return False 1057 time.sleep(WAIT_TIME_VOICE_MAIL_SERVER_RESPONSE) 1058 callId = ad.droid.telecomCallGetCallIds()[0] 1059 time.sleep(WAIT_TIME_VOICE_MAIL_SERVER_RESPONSE) 1060 count = MAX_SAVED_VOICE_MAIL 1061 while (is_phone_in_call(log, ad) and (count > 0)): 1062 log.info("Press 7 to delete voice mail.") 1063 ad.droid.telecomCallPlayDtmfTone(callId, VOICEMAIL_DELETE_DIGIT) 1064 ad.droid.telecomCallStopDtmfTone(callId) 1065 time.sleep(WAIT_TIME_VOICE_MAIL_SERVER_RESPONSE) 1066 count -= 1 1067 log.info("Voice mail server dropped this call.") 1068 # wait for telephonyGetVoiceMailCount to update correct result 1069 remaining_time = MAX_WAIT_TIME_VOICE_MAIL_COUNT 1070 while ((remaining_time > 0) and 1071 (ad.droid.telephonyGetVoiceMailCount() != 0)): 1072 time.sleep(1) 1073 remaining_time -= 1 1074 current_voice_mail_count = ad.droid.telephonyGetVoiceMailCount() 1075 log.info("telephonyGetVoiceMailCount: {}".format(current_voice_mail_count)) 1076 return (current_voice_mail_count == 0) 1077 1078 1079def _is_on_message_waiting_event_true(event): 1080 """Private function to return if the received EventMessageWaitingIndicatorChanged 1081 event MessageWaitingIndicatorContainer.IS_MESSAGE_WAITING field is True. 1082 """ 1083 return event['data'][MessageWaitingIndicatorContainer.IS_MESSAGE_WAITING] 1084 1085 1086def call_setup_teardown(log, 1087 ad_caller, 1088 ad_callee, 1089 ad_hangup=None, 1090 verify_caller_func=None, 1091 verify_callee_func=None, 1092 wait_time_in_call=WAIT_TIME_IN_CALL, 1093 incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND): 1094 """ Call process, including make a phone call from caller, 1095 accept from callee, and hang up. The call is on default voice subscription 1096 1097 In call process, call from <droid_caller> to <droid_callee>, 1098 accept the call, (optional)then hang up from <droid_hangup>. 1099 1100 Args: 1101 ad_caller: Caller Android Device Object. 1102 ad_callee: Callee Android Device Object. 1103 ad_hangup: Android Device Object end the phone call. 1104 Optional. Default value is None, and phone call will continue. 1105 verify_call_mode_caller: func_ptr to verify caller in correct mode 1106 Optional. Default is None 1107 verify_call_mode_caller: func_ptr to verify caller in correct mode 1108 Optional. Default is None 1109 incall_ui_display: after answer the call, bring in-call UI to foreground or 1110 background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND. 1111 if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground. 1112 if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background. 1113 else, do nothing. 1114 1115 Returns: 1116 True if call process without any error. 1117 False if error happened. 1118 1119 """ 1120 subid_caller = get_outgoing_voice_sub_id(ad_caller) 1121 subid_callee = get_incoming_voice_sub_id(ad_callee) 1122 log.info("Sub-ID Caller {}, Sub-ID Callee {}".format(subid_caller, 1123 subid_callee)) 1124 return call_setup_teardown_for_subscription( 1125 log, ad_caller, ad_callee, subid_caller, subid_callee, ad_hangup, 1126 verify_caller_func, verify_callee_func, wait_time_in_call, 1127 incall_ui_display) 1128 1129 1130def call_setup_teardown_for_subscription( 1131 log, 1132 ad_caller, 1133 ad_callee, 1134 subid_caller, 1135 subid_callee, 1136 ad_hangup=None, 1137 verify_caller_func=None, 1138 verify_callee_func=None, 1139 wait_time_in_call=WAIT_TIME_IN_CALL, 1140 incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND): 1141 """ Call process, including make a phone call from caller, 1142 accept from callee, and hang up. The call is on specified subscription 1143 1144 In call process, call from <droid_caller> to <droid_callee>, 1145 accept the call, (optional)then hang up from <droid_hangup>. 1146 1147 Args: 1148 ad_caller: Caller Android Device Object. 1149 ad_callee: Callee Android Device Object. 1150 subid_caller: Caller subscription ID 1151 subid_callee: Callee subscription ID 1152 ad_hangup: Android Device Object end the phone call. 1153 Optional. Default value is None, and phone call will continue. 1154 verify_call_mode_caller: func_ptr to verify caller in correct mode 1155 Optional. Default is None 1156 verify_call_mode_caller: func_ptr to verify caller in correct mode 1157 Optional. Default is None 1158 incall_ui_display: after answer the call, bring in-call UI to foreground or 1159 background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND. 1160 if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground. 1161 if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background. 1162 else, do nothing. 1163 1164 Returns: 1165 True if call process without any error. 1166 False if error happened. 1167 1168 """ 1169 CHECK_INTERVAL = 3 1170 1171 class _CallSequenceException(Exception): 1172 pass 1173 1174 caller_number = ad_caller.cfg['subscription'][subid_caller]['phone_num'] 1175 callee_number = ad_callee.cfg['subscription'][subid_callee]['phone_num'] 1176 1177 log.info("Call from {} to {}".format(caller_number, callee_number)) 1178 1179 try: 1180 if not initiate_call(log, ad_caller, callee_number): 1181 raise _CallSequenceException("Initiate call failed.") 1182 1183 if not wait_and_answer_call_for_subscription( 1184 log, 1185 ad_callee, 1186 subid_callee, 1187 incoming_number=caller_number, 1188 incall_ui_display=incall_ui_display): 1189 raise _CallSequenceException("Answer call fail.") 1190 1191 # ensure that all internal states are updated in telecom 1192 time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) 1193 1194 if verify_caller_func and not verify_caller_func(log, ad_caller): 1195 raise _CallSequenceException("Caller not in correct state!") 1196 if verify_callee_func and not verify_callee_func(log, ad_callee): 1197 raise _CallSequenceException("Callee not in correct state!") 1198 1199 elapsed_time = 0 1200 while (elapsed_time < wait_time_in_call): 1201 CHECK_INTERVAL = min(CHECK_INTERVAL, 1202 wait_time_in_call - elapsed_time) 1203 time.sleep(CHECK_INTERVAL) 1204 elapsed_time += CHECK_INTERVAL 1205 if not verify_caller_func: 1206 caller_state_result = ad_caller.droid.telecomIsInCall() 1207 else: 1208 caller_state_result = verify_caller_func(log, ad_caller) 1209 if not caller_state_result: 1210 raise _CallSequenceException( 1211 "Caller not in correct state at <{}>/<{}> second.".format( 1212 elapsed_time, wait_time_in_call)) 1213 if not verify_callee_func: 1214 callee_state_result = ad_callee.droid.telecomIsInCall() 1215 else: 1216 callee_state_result = verify_callee_func(log, ad_callee) 1217 if not callee_state_result: 1218 raise _CallSequenceException( 1219 "Callee not in correct state at <{}>/<{}> second.".format( 1220 elapsed_time, wait_time_in_call)) 1221 1222 if not ad_hangup: 1223 return True 1224 1225 if not hangup_call(log, ad_hangup): 1226 raise _CallSequenceException("Error in Hanging-Up Call") 1227 1228 return True 1229 1230 except _CallSequenceException as e: 1231 log.error(e) 1232 return False 1233 finally: 1234 if ad_hangup: 1235 for ad in [ad_caller, ad_callee]: 1236 try: 1237 if ad.droid.telecomIsInCall(): 1238 ad.droid.telecomEndCall() 1239 except Exception as e: 1240 log.error(str(e)) 1241 1242 1243def phone_number_formatter(input_string, format=None): 1244 """Get expected format of input phone number string. 1245 1246 Args: 1247 input_string: (string) input phone number. 1248 The input could be 10/11/12 digital, with or without " "/"-"/"." 1249 format: (int) expected format, this could be 7/10/11/12 1250 if format is 7: output string would be 7 digital number. 1251 if format is 10: output string would be 10 digital (standard) number. 1252 if format is 11: output string would be "1" + 10 digital number. 1253 if format is 12: output string would be "+1" + 10 digital number. 1254 1255 Returns: 1256 If no error happen, return phone number in expected format. 1257 Else, return None. 1258 """ 1259 # make sure input_string is 10 digital 1260 # Remove white spaces, dashes, dots 1261 input_string = input_string.replace(" ", "").replace("-", "").replace(".", 1262 "") 1263 if not format: 1264 return input_string 1265 # Remove "1" or "+1"from front 1266 if (len(input_string) == PHONE_NUMBER_STRING_FORMAT_11_DIGIT and 1267 input_string[0] == "1"): 1268 input_string = input_string[1:] 1269 elif (len(input_string) == PHONE_NUMBER_STRING_FORMAT_12_DIGIT and 1270 input_string[0:2] == "+1"): 1271 input_string = input_string[2:] 1272 elif (len(input_string) == PHONE_NUMBER_STRING_FORMAT_7_DIGIT and 1273 format == PHONE_NUMBER_STRING_FORMAT_7_DIGIT): 1274 return input_string 1275 elif len(input_string) != PHONE_NUMBER_STRING_FORMAT_10_DIGIT: 1276 return None 1277 # change input_string according to format 1278 if format == PHONE_NUMBER_STRING_FORMAT_12_DIGIT: 1279 input_string = "+1" + input_string 1280 elif format == PHONE_NUMBER_STRING_FORMAT_11_DIGIT: 1281 input_string = "1" + input_string 1282 elif format == PHONE_NUMBER_STRING_FORMAT_10_DIGIT: 1283 input_string = input_string 1284 elif format == PHONE_NUMBER_STRING_FORMAT_7_DIGIT: 1285 input_string = input_string[3:] 1286 else: 1287 return None 1288 return input_string 1289 1290 1291def get_internet_connection_type(log, ad): 1292 """Get current active connection type name. 1293 1294 Args: 1295 log: Log object. 1296 ad: Android Device Object. 1297 Returns: 1298 current active connection type name. 1299 """ 1300 if not ad.droid.connectivityNetworkIsConnected(): 1301 return 'none' 1302 return connection_type_from_type_string( 1303 ad.droid.connectivityNetworkGetActiveConnectionTypeName()) 1304 1305 1306def verify_http_connection(log, 1307 ad, 1308 url="http://www.google.com/", 1309 retry=3, 1310 retry_interval=5): 1311 """Make ping request and return status. 1312 1313 Args: 1314 ad: Android Device Object. 1315 url: Optional. The ping request will be made to this URL. 1316 Default Value is "http://www.google.com/". 1317 1318 """ 1319 for i in range(0, retry + 1): 1320 1321 try: 1322 http_response = ad.droid.httpPing(url) 1323 except: 1324 http_response = None 1325 1326 # If httpPing failed, it may return {} (if phone just turn off APM) or 1327 # None (regular fail) 1328 # So here use "if http_response" to see if it pass or fail 1329 if http_response: 1330 log.info("Verify Internet succeeded after {}s.".format( 1331 i * retry_interval) if i > 0 else "Verify Internet succeeded.") 1332 return True 1333 else: 1334 if i < retry: 1335 time.sleep(retry_interval) 1336 log.info("Verify Internet retry failed after {}s" 1337 .format(i * retry_interval)) 1338 return False 1339 1340 1341def _connection_state_change(_event, target_state, connection_type): 1342 if connection_type: 1343 if 'TypeName' not in _event['data']: 1344 return False 1345 connection_type_string_in_event = _event['data']['TypeName'] 1346 cur_type = connection_type_from_type_string( 1347 connection_type_string_in_event) 1348 if cur_type != connection_type: 1349 log.info( 1350 "_connection_state_change expect: {}, received: {} <type {}>".format( 1351 connection_type, connection_type_string_in_event, 1352 cur_type)) 1353 return False 1354 1355 if 'isConnected' in _event['data'] and _event['data'][ 1356 'isConnected'] == target_state: 1357 return True 1358 return False 1359 1360 1361def wait_for_cell_data_connection( 1362 log, 1363 ad, 1364 state, 1365 timeout_value=EventDispatcher.DEFAULT_TIMEOUT): 1366 """Wait for data connection status to be expected value for default 1367 data subscription. 1368 1369 Wait for the data connection status to be DATA_STATE_CONNECTED 1370 or DATA_STATE_DISCONNECTED. 1371 1372 Args: 1373 log: Log object. 1374 ad: Android Device Object. 1375 state: Expected status: True or False. 1376 If True, it will wait for status to be DATA_STATE_CONNECTED. 1377 If False, it will wait for status ti be DATA_STATE_DISCONNECTED. 1378 timeout_value: wait for cell data timeout value. 1379 This is optional, default value is EventDispatcher.DEFAULT_TIMEOUT 1380 1381 Returns: 1382 True if success. 1383 False if failed. 1384 """ 1385 sub_id = get_default_data_sub_id(ad) 1386 return wait_for_cell_data_connection_for_subscription(log, ad, sub_id, 1387 state, timeout_value) 1388 1389 1390def _is_data_connection_state_match(log, ad, expected_data_connection_state): 1391 return (expected_data_connection_state == 1392 ad.droid.telephonyGetDataConnectionState()) 1393 1394 1395def _is_network_connected_state_match(log, ad, 1396 expected_network_connected_state): 1397 return (expected_network_connected_state == 1398 ad.droid.connectivityNetworkIsConnected()) 1399 1400 1401def wait_for_cell_data_connection_for_subscription( 1402 log, 1403 ad, 1404 sub_id, 1405 state, 1406 timeout_value=EventDispatcher.DEFAULT_TIMEOUT): 1407 """Wait for data connection status to be expected value for specified 1408 subscrption id. 1409 1410 Wait for the data connection status to be DATA_STATE_CONNECTED 1411 or DATA_STATE_DISCONNECTED. 1412 1413 Args: 1414 log: Log object. 1415 ad: Android Device Object. 1416 sub_id: subscription Id 1417 state: Expected status: True or False. 1418 If True, it will wait for status to be DATA_STATE_CONNECTED. 1419 If False, it will wait for status ti be DATA_STATE_DISCONNECTED. 1420 timeout_value: wait for cell data timeout value. 1421 This is optional, default value is EventDispatcher.DEFAULT_TIMEOUT 1422 1423 Returns: 1424 True if success. 1425 False if failed. 1426 """ 1427 state_str = { 1428 True: DATA_STATE_CONNECTED, 1429 False: DATA_STATE_DISCONNECTED 1430 }[state] 1431 1432 ad.ed.clear_all_events() 1433 ad.droid.telephonyStartTrackingDataConnectionStateChangeForSubscription( 1434 sub_id) 1435 ad.droid.connectivityStartTrackingConnectivityStateChange() 1436 try: 1437 # TODO: b/26293147 There is no framework API to get data connection 1438 # state by sub id 1439 data_state = ad.droid.telephonyGetDataConnectionState() 1440 if data_state == state_str: 1441 return _wait_for_nw_data_connection( 1442 log, ad, state, NETWORK_CONNECTION_TYPE_CELL, timeout_value) 1443 1444 try: 1445 event = ad.ed.wait_for_event( 1446 EventDataConnectionStateChanged, 1447 is_event_match, 1448 timeout=timeout_value, 1449 field=DataConnectionStateContainer.DATA_CONNECTION_STATE, 1450 value=state_str) 1451 except Empty: 1452 log.debug( 1453 "No expected event EventDataConnectionStateChanged {}.".format( 1454 state_str)) 1455 1456 # TODO: Wait for <MAX_WAIT_TIME_CONNECTION_STATE_UPDATE> seconds for 1457 # data connection state. 1458 # Otherwise, the network state will not be correct. 1459 # The bug is tracked here: b/20921915 1460 1461 # Previously we use _is_data_connection_state_match, 1462 # but telephonyGetDataConnectionState sometimes return wrong value. 1463 # The bug is tracked here: b/22612607 1464 # So we use _is_network_connected_state_match. 1465 1466 if _wait_for_droid_in_state(log, ad, 1467 MAX_WAIT_TIME_CONNECTION_STATE_UPDATE, 1468 _is_network_connected_state_match, state): 1469 return _wait_for_nw_data_connection( 1470 log, ad, state, NETWORK_CONNECTION_TYPE_CELL, timeout_value) 1471 else: 1472 return False 1473 1474 finally: 1475 ad.droid.telephonyStopTrackingDataConnectionStateChangeForSubscription( 1476 sub_id) 1477 1478 1479def wait_for_wifi_data_connection( 1480 log, 1481 ad, 1482 state, 1483 timeout_value=EventDispatcher.DEFAULT_TIMEOUT): 1484 """Wait for data connection status to be expected value and connection is by WiFi. 1485 1486 Args: 1487 log: Log object. 1488 ad: Android Device Object. 1489 state: Expected status: True or False. 1490 If True, it will wait for status to be DATA_STATE_CONNECTED. 1491 If False, it will wait for status ti be DATA_STATE_DISCONNECTED. 1492 timeout_value: wait for network data timeout value. 1493 This is optional, default value is EventDispatcher.DEFAULT_TIMEOUT 1494 1495 Returns: 1496 True if success. 1497 False if failed. 1498 """ 1499 log.info("{} wait_for_wifi_data_connection".format(ad.serial)) 1500 return _wait_for_nw_data_connection( 1501 log, ad, state, NETWORK_CONNECTION_TYPE_WIFI, timeout_value) 1502 1503 1504def wait_for_data_connection(log, 1505 ad, 1506 state, 1507 timeout_value=EventDispatcher.DEFAULT_TIMEOUT): 1508 """Wait for data connection status to be expected value. 1509 1510 Wait for the data connection status to be DATA_STATE_CONNECTED 1511 or DATA_STATE_DISCONNECTED. 1512 1513 Args: 1514 log: Log object. 1515 ad: Android Device Object. 1516 state: Expected status: True or False. 1517 If True, it will wait for status to be DATA_STATE_CONNECTED. 1518 If False, it will wait for status ti be DATA_STATE_DISCONNECTED. 1519 timeout_value: wait for network data timeout value. 1520 This is optional, default value is EventDispatcher.DEFAULT_TIMEOUT 1521 1522 Returns: 1523 True if success. 1524 False if failed. 1525 """ 1526 return _wait_for_nw_data_connection(log, ad, state, None, timeout_value) 1527 1528 1529def _wait_for_nw_data_connection( 1530 log, 1531 ad, 1532 is_connected, 1533 connection_type=None, 1534 timeout_value=EventDispatcher.DEFAULT_TIMEOUT): 1535 """Wait for data connection status to be expected value. 1536 1537 Wait for the data connection status to be DATA_STATE_CONNECTED 1538 or DATA_STATE_DISCONNECTED. 1539 1540 Args: 1541 log: Log object. 1542 ad: Android Device Object. 1543 is_connected: Expected connection status: True or False. 1544 If True, it will wait for status to be DATA_STATE_CONNECTED. 1545 If False, it will wait for status ti be DATA_STATE_DISCONNECTED. 1546 connection_type: expected connection type. 1547 This is optional, if it is None, then any connection type will return True. 1548 timeout_value: wait for network data timeout value. 1549 This is optional, default value is EventDispatcher.DEFAULT_TIMEOUT 1550 1551 Returns: 1552 True if success. 1553 False if failed. 1554 """ 1555 ad.ed.clear_all_events() 1556 ad.droid.connectivityStartTrackingConnectivityStateChange() 1557 try: 1558 cur_data_connection_state = ad.droid.connectivityNetworkIsConnected() 1559 if is_connected == cur_data_connection_state: 1560 current_type = get_internet_connection_type(log, ad) 1561 log.info( 1562 "_wait_for_nw_data_connection: current connection type: {}".format( 1563 current_type)) 1564 if not connection_type: 1565 return True 1566 else: 1567 if not is_connected and current_type != connection_type: 1568 log.info( 1569 "wait_for_nw_data_connection success: {} data not on {}!".format( 1570 ad.serial, connection_type)) 1571 return True 1572 elif is_connected and current_type == connection_type: 1573 log.info( 1574 "wait_for_nw_data_connection success: {} data on {}!".format( 1575 ad.serial, connection_type)) 1576 return True 1577 else: 1578 log.info("{} current state: {} target: {}".format( 1579 ad.serial, cur_data_connection_state, is_connected)) 1580 1581 try: 1582 event = ad.ed.wait_for_event( 1583 EventConnectivityChanged, _connection_state_change, 1584 timeout_value, is_connected, connection_type) 1585 log.info("_wait_for_nw_data_connection received event:{}".format( 1586 event)) 1587 except Empty: 1588 pass 1589 1590 log.info( 1591 "_wait_for_nw_data_connection: check connection after wait event.") 1592 # TODO: Wait for <MAX_WAIT_TIME_CONNECTION_STATE_UPDATE> seconds for 1593 # data connection state. 1594 # Otherwise, the network state will not be correct. 1595 # The bug is tracked here: b/20921915 1596 if _wait_for_droid_in_state( 1597 log, ad, MAX_WAIT_TIME_CONNECTION_STATE_UPDATE, 1598 _is_network_connected_state_match, is_connected): 1599 current_type = get_internet_connection_type(log, ad) 1600 log.info( 1601 "_wait_for_nw_data_connection: current connection type: {}".format( 1602 current_type)) 1603 if not connection_type: 1604 return True 1605 else: 1606 if not is_connected and current_type != connection_type: 1607 log.info( 1608 "wait_for_nw_data_connection after event wait, success: {} data not on {}!".format( 1609 ad.serial, connection_type)) 1610 return True 1611 elif is_connected and current_type == connection_type: 1612 log.info( 1613 "wait_for_nw_data_connection after event wait, success: {} data on {}!".format( 1614 ad.serial, connection_type)) 1615 return True 1616 else: 1617 return False 1618 else: 1619 return False 1620 except Exception as e: 1621 log.error( 1622 "tel_test_utils._wait_for_nw_data_connection threw Random exception {}".format( 1623 str(e))) 1624 return False 1625 finally: 1626 ad.droid.connectivityStopTrackingConnectivityStateChange() 1627 1628 1629def verify_incall_state(log, ads, expected_status): 1630 """Verify phones in incall state or not. 1631 1632 Verify if all phones in the array <ads> are in <expected_status>. 1633 1634 Args: 1635 log: Log object. 1636 ads: Array of Android Device Object. All droid in this array will be tested. 1637 expected_status: If True, verify all Phones in incall state. 1638 If False, verify all Phones not in incall state. 1639 1640 """ 1641 result = True 1642 for ad in ads: 1643 if ad.droid.telecomIsInCall() is not expected_status: 1644 log.error("Verify_incall_state: {} status:{}, expected:{}".format( 1645 ad.serial, ad.droid.telecomIsInCall(), expected_status)) 1646 result = False 1647 return result 1648 1649 1650def verify_active_call_number(log, ad, expected_number): 1651 """Verify the number of current active call. 1652 1653 Verify if the number of current active call in <ad> is 1654 equal to <expected_number>. 1655 1656 Args: 1657 ad: Android Device Object. 1658 expected_number: Expected active call number. 1659 """ 1660 calls = ad.droid.telecomCallGetCallIds() 1661 if calls is None: 1662 actual_number = 0 1663 else: 1664 actual_number = len(calls) 1665 if actual_number != expected_number: 1666 log.error("Active Call number in {}".format(ad.serial)) 1667 log.error("Expected:{}, Actual:{}".format(expected_number, 1668 actual_number)) 1669 return False 1670 return True 1671 1672 1673def num_active_calls(log, ad): 1674 """Get the count of current active calls. 1675 1676 Args: 1677 log: Log object. 1678 ad: Android Device Object. 1679 1680 Returns: 1681 Count of current active calls. 1682 """ 1683 calls = ad.droid.telecomCallGetCallIds() 1684 return len(calls) if calls else 0 1685 1686 1687def toggle_volte(log, ad, new_state=None): 1688 """Toggle enable/disable VoLTE for default voice subscription. 1689 1690 Args: 1691 ad: Android device object. 1692 new_state: VoLTE mode state to set to. 1693 True for enable, False for disable. 1694 If None, opposite of the current state. 1695 1696 Raises: 1697 TelTestUtilsError if platform does not support VoLTE. 1698 """ 1699 return toggle_volte_for_subscription( 1700 log, ad, get_outgoing_voice_sub_id(ad), new_state) 1701 1702 1703def toggle_volte_for_subscription(log, ad, sub_id, new_state=None): 1704 """Toggle enable/disable VoLTE for specified voice subscription. 1705 1706 Args: 1707 ad: Android device object. 1708 sub_id: subscription ID 1709 new_state: VoLTE mode state to set to. 1710 True for enable, False for disable. 1711 If None, opposite of the current state. 1712 1713 Raises: 1714 TelTestUtilsError if platform does not support VoLTE. 1715 """ 1716 # TODO: b/26293960 No framework API available to set IMS by SubId. 1717 if not ad.droid.imsIsEnhanced4gLteModeSettingEnabledByPlatform(): 1718 raise TelTestUtilsError("VoLTE not supported by platform.") 1719 current_state = ad.droid.imsIsEnhanced4gLteModeSettingEnabledByUser() 1720 if new_state is None: 1721 new_state = not current_state 1722 if new_state != current_state: 1723 ad.droid.imsSetEnhanced4gMode(new_state) 1724 return True 1725 1726 1727def set_wfc_mode(log, ad, wfc_mode): 1728 """Set WFC enable/disable and mode. 1729 1730 Args: 1731 log: Log object 1732 ad: Android device object. 1733 wfc_mode: WFC mode to set to. 1734 Valid mode includes: WFC_MODE_WIFI_ONLY, WFC_MODE_CELLULAR_PREFERRED, 1735 WFC_MODE_WIFI_PREFERRED, WFC_MODE_DISABLED. 1736 1737 Returns: 1738 True if success. False if ad does not support WFC or error happened. 1739 """ 1740 try: 1741 log.info("{} set wfc mode to {}".format(ad.serial, wfc_mode)) 1742 if not ad.droid.imsIsWfcEnabledByPlatform(): 1743 if wfc_mode == WFC_MODE_DISABLED: 1744 return True 1745 else: 1746 log.error("WFC not supported by platform.") 1747 return False 1748 1749 ad.droid.imsSetWfcMode(wfc_mode) 1750 1751 except Exception as e: 1752 log.error(e) 1753 return False 1754 1755 return True 1756 1757 1758def _wait_for_droid_in_state(log, ad, max_time, state_check_func, *args, 1759 **kwargs): 1760 while max_time > 0: 1761 if state_check_func(log, ad, *args, **kwargs): 1762 return True 1763 1764 time.sleep(1) 1765 max_time -= 1 1766 1767 return False 1768 1769 1770def _wait_for_droid_in_state_for_subscription( 1771 log, ad, sub_id, max_time, state_check_func, *args, **kwargs): 1772 while max_time > 0: 1773 if state_check_func(log, ad, sub_id, *args, **kwargs): 1774 return True 1775 1776 time.sleep(1) 1777 max_time -= 1 1778 1779 return False 1780 1781 1782def _wait_for_droids_in_state(log, ads, max_time, state_check_func, *args, 1783 **kwargs): 1784 while max_time > 0: 1785 success = True 1786 for ad in ads: 1787 if not state_check_func(log, ad, *args, **kwargs): 1788 success = False 1789 break 1790 if success: 1791 return True 1792 1793 time.sleep(1) 1794 max_time -= 1 1795 1796 return False 1797 1798 1799def is_phone_in_call(log, ad): 1800 """Return True if phone in call. 1801 1802 Args: 1803 log: log object. 1804 ad: android device. 1805 """ 1806 return ad.droid.telecomIsInCall() 1807 1808 1809def is_phone_not_in_call(log, ad): 1810 """Return True if phone not in call. 1811 1812 Args: 1813 log: log object. 1814 ad: android device. 1815 """ 1816 return not ad.droid.telecomIsInCall() 1817 1818 1819def wait_for_droid_in_call(log, ad, max_time): 1820 """Wait for android to be in call state. 1821 1822 Args: 1823 log: log object. 1824 ad: android device. 1825 max_time: maximal wait time. 1826 1827 Returns: 1828 If phone become in call state within max_time, return True. 1829 Return False if timeout. 1830 """ 1831 return _wait_for_droid_in_state(log, ad, max_time, is_phone_in_call) 1832 1833 1834def wait_for_telecom_ringing(log, ad, max_time=MAX_WAIT_TIME_TELECOM_RINGING): 1835 """Wait for android to be in telecom ringing state. 1836 1837 Args: 1838 log: log object. 1839 ad: android device. 1840 max_time: maximal wait time. This is optional. 1841 Default Value is MAX_WAIT_TIME_TELECOM_RINGING. 1842 1843 Returns: 1844 If phone become in telecom ringing state within max_time, return True. 1845 Return False if timeout. 1846 """ 1847 return _wait_for_droid_in_state( 1848 log, ad, max_time, lambda log, ad: ad.droid.telecomIsRinging()) 1849 1850 1851def wait_for_droid_not_in_call(log, ad, max_time): 1852 """Wait for android to be not in call state. 1853 1854 Args: 1855 log: log object. 1856 ad: android device. 1857 max_time: maximal wait time. 1858 1859 Returns: 1860 If phone become not in call state within max_time, return True. 1861 Return False if timeout. 1862 """ 1863 return _wait_for_droid_in_state(log, ad, max_time, is_phone_not_in_call) 1864 1865 1866def _is_attached(log, ad, voice_or_data): 1867 return _is_attached_for_subscription( 1868 log, ad, ad.droid.subscriptionGetDefaultSubId(), voice_or_data) 1869 1870 1871def _is_attached_for_subscription(log, ad, sub_id, voice_or_data): 1872 if get_network_rat_for_subscription(log, ad, sub_id, 1873 voice_or_data) != RAT_UNKNOWN: 1874 return True 1875 else: 1876 return False 1877 1878 1879def wait_for_voice_attach(log, ad, max_time): 1880 """Wait for android device to attach on voice. 1881 1882 Args: 1883 log: log object. 1884 ad: android device. 1885 max_time: maximal wait time. 1886 1887 Returns: 1888 Return True if device attach voice within max_time. 1889 Return False if timeout. 1890 """ 1891 return _wait_for_droid_in_state(log, ad, max_time, _is_attached, 1892 NETWORK_SERVICE_VOICE) 1893 1894 1895def wait_for_voice_attach_for_subscription(log, ad, sub_id, max_time): 1896 """Wait for android device to attach on voice in subscription id. 1897 1898 Args: 1899 log: log object. 1900 ad: android device. 1901 sub_id: subscription id. 1902 max_time: maximal wait time. 1903 1904 Returns: 1905 Return True if device attach voice within max_time. 1906 Return False if timeout. 1907 """ 1908 if not _wait_for_droid_in_state_for_subscription( 1909 log, ad, sub_id, max_time, _is_attached_for_subscription, 1910 NETWORK_SERVICE_VOICE): 1911 return False 1912 1913 # TODO: b/26295983 if pone attach to 1xrtt from unknown, phone may not 1914 # receive incoming call immediately. 1915 if ad.droid.telephonyGetCurrentVoiceNetworkType() == RAT_1XRTT: 1916 time.sleep(WAIT_TIME_1XRTT_VOICE_ATTACH) 1917 return True 1918 1919 1920def wait_for_data_attach(log, ad, max_time): 1921 """Wait for android device to attach on data. 1922 1923 Args: 1924 log: log object. 1925 ad: android device. 1926 max_time: maximal wait time. 1927 1928 Returns: 1929 Return True if device attach data within max_time. 1930 Return False if timeout. 1931 """ 1932 return _wait_for_droid_in_state(log, ad, max_time, _is_attached, 1933 NETWORK_SERVICE_DATA) 1934 1935 1936def wait_for_data_attach_for_subscription(log, ad, sub_id, max_time): 1937 """Wait for android device to attach on data in subscription id. 1938 1939 Args: 1940 log: log object. 1941 ad: android device. 1942 sub_id: subscription id. 1943 max_time: maximal wait time. 1944 1945 Returns: 1946 Return True if device attach data within max_time. 1947 Return False if timeout. 1948 """ 1949 return _wait_for_droid_in_state_for_subscription( 1950 log, ad, sub_id, max_time, _is_attached_for_subscription, 1951 NETWORK_SERVICE_DATA) 1952 1953 1954def is_ims_registered(log, ad): 1955 """Return True if IMS registered. 1956 1957 Args: 1958 log: log object. 1959 ad: android device. 1960 1961 Returns: 1962 Return True if IMS registered. 1963 Return False if IMS not registered. 1964 """ 1965 return ad.droid.telephonyIsImsRegistered() 1966 1967 1968def wait_for_ims_registered(log, ad, max_time): 1969 """Wait for android device to register on ims. 1970 1971 Args: 1972 log: log object. 1973 ad: android device. 1974 max_time: maximal wait time. 1975 1976 Returns: 1977 Return True if device register ims successfully within max_time. 1978 Return False if timeout. 1979 """ 1980 return _wait_for_droid_in_state(log, ad, max_time, is_ims_registered) 1981 1982 1983def is_volte_enabled(log, ad): 1984 """Return True if VoLTE feature bit is True. 1985 1986 Args: 1987 log: log object. 1988 ad: android device. 1989 1990 Returns: 1991 Return True if VoLTE feature bit is True and IMS registered. 1992 Return False if VoLTE feature bit is False or IMS not registered. 1993 """ 1994 volte_status = ad.droid.telephonyIsVolteAvailable() 1995 ims_status = is_ims_registered(log, ad) 1996 if volte_status is True and ims_status is False: 1997 log.error("Error! VoLTE is Available, but IMS is not registered.") 1998 return False 1999 return volte_status 2000 2001 2002def is_video_enabled(log, ad): 2003 """Return True if Video Calling feature bit is True. 2004 2005 Args: 2006 log: log object. 2007 ad: android device. 2008 2009 Returns: 2010 Return True if Video Calling feature bit is True and IMS registered. 2011 Return False if Video Calling feature bit is False or IMS not registered. 2012 """ 2013 video_status = ad.droid.telephonyIsVideoCallingAvailable() 2014 ims_status = is_ims_registered(log, ad) 2015 if video_status is True and ims_status is False: 2016 log.error("Error! Video Call is Available, but IMS is not registered.") 2017 return False 2018 return video_status 2019 2020 2021def wait_for_volte_enabled(log, ad, max_time): 2022 """Wait for android device to report VoLTE enabled bit true. 2023 2024 Args: 2025 log: log object. 2026 ad: android device. 2027 max_time: maximal wait time. 2028 2029 Returns: 2030 Return True if device report VoLTE enabled bit true within max_time. 2031 Return False if timeout. 2032 """ 2033 return _wait_for_droid_in_state(log, ad, max_time, is_volte_enabled) 2034 2035 2036def wait_for_video_enabled(log, ad, max_time): 2037 """Wait for android device to report Video Telephony enabled bit true. 2038 2039 Args: 2040 log: log object. 2041 ad: android device. 2042 max_time: maximal wait time. 2043 2044 Returns: 2045 Return True if device report Video Telephony enabled bit true within max_time. 2046 Return False if timeout. 2047 """ 2048 return _wait_for_droid_in_state(log, ad, max_time, is_video_enabled) 2049 2050 2051def is_wfc_enabled(log, ad): 2052 """Return True if WiFi Calling feature bit is True. 2053 2054 Args: 2055 log: log object. 2056 ad: android device. 2057 2058 Returns: 2059 Return True if WiFi Calling feature bit is True and IMS registered. 2060 Return False if WiFi Calling feature bit is False or IMS not registered. 2061 """ 2062 wfc_status = ad.droid.telephonyIsWifiCallingAvailable() 2063 ims_status = is_ims_registered(log, ad) 2064 if wfc_status is True and ims_status is False: 2065 log.error( 2066 "Error! WiFi Calling is Available, but IMS is not registered.") 2067 return False 2068 return wfc_status 2069 2070 2071def wait_for_wfc_enabled(log, ad, max_time=MAX_WAIT_TIME_WFC_ENABLED): 2072 """Wait for android device to report WiFi Calling enabled bit true. 2073 2074 Args: 2075 log: log object. 2076 ad: android device. 2077 max_time: maximal wait time. 2078 Default value is MAX_WAIT_TIME_WFC_ENABLED. 2079 2080 Returns: 2081 Return True if device report WiFi Calling enabled bit true within max_time. 2082 Return False if timeout. 2083 """ 2084 return _wait_for_droid_in_state(log, ad, max_time, is_wfc_enabled) 2085 2086 2087def wait_for_wfc_disabled(log, ad, max_time=MAX_WAIT_TIME_WFC_DISABLED): 2088 """Wait for android device to report WiFi Calling enabled bit false. 2089 2090 Args: 2091 log: log object. 2092 ad: android device. 2093 max_time: maximal wait time. 2094 Default value is MAX_WAIT_TIME_WFC_DISABLED. 2095 2096 Returns: 2097 Return True if device report WiFi Calling enabled bit false within max_time. 2098 Return False if timeout. 2099 """ 2100 return _wait_for_droid_in_state( 2101 log, ad, max_time, lambda log, ad: not is_wfc_enabled(log, ad)) 2102 2103 2104def get_phone_number(log, ad): 2105 """Get phone number for default subscription 2106 2107 Args: 2108 log: log object. 2109 ad: Android device object. 2110 2111 Returns: 2112 Phone number. 2113 """ 2114 return get_phone_number_for_subscription(log, ad, 2115 get_outgoing_voice_sub_id(ad)) 2116 2117 2118def get_phone_number_for_subscription(log, ad, subid): 2119 """Get phone number for subscription 2120 2121 Args: 2122 log: log object. 2123 ad: Android device object. 2124 subid: subscription id. 2125 2126 Returns: 2127 Phone number. 2128 """ 2129 number = None 2130 try: 2131 number = ad.cfg['subscription'][subid]['phone_num'] 2132 except KeyError: 2133 number = ad.droid.telephonyGetLine1NumberForSubscription(subid) 2134 return number 2135 2136 2137def set_phone_number(log, ad, phone_num): 2138 """Set phone number for default subscription 2139 2140 Args: 2141 log: log object. 2142 ad: Android device object. 2143 phone_num: phone number string. 2144 2145 Returns: 2146 True if success. 2147 """ 2148 return set_phone_number_for_subscription( 2149 log, ad, get_outgoing_voice_sub_id(ad), phone_num) 2150 2151 2152def set_phone_number_for_subscription(log, ad, subid, phone_num): 2153 """Set phone number for subscription 2154 2155 Args: 2156 log: log object. 2157 ad: Android device object. 2158 subid: subscription id. 2159 phone_num: phone number string. 2160 2161 Returns: 2162 True if success. 2163 """ 2164 try: 2165 ad.cfg['subscription'][subid]['phone_num'] = phone_num 2166 except Exception: 2167 return False 2168 return True 2169 2170 2171def get_operator_name(log, ad, subId=None): 2172 """Get operator name (e.g. vzw, tmo) of droid. 2173 2174 Args: 2175 ad: Android device object. 2176 sub_id: subscription ID 2177 Optional, default is None 2178 2179 Returns: 2180 Operator name. 2181 """ 2182 try: 2183 if subId is not None: 2184 result = operator_name_from_plmn_id( 2185 ad.droid.telephonyGetSimOperatorForSubscription(subId)) 2186 else: 2187 result = operator_name_from_plmn_id( 2188 ad.droid.telephonyGetSimOperator()) 2189 except KeyError: 2190 result = CARRIER_UNKNOWN 2191 return result 2192 2193 2194def get_model_name(ad): 2195 """Get android device model name 2196 2197 Args: 2198 ad: Android device object 2199 2200 Returns: 2201 model name string 2202 """ 2203 # TODO: Create translate table. 2204 model = ad.model 2205 if (model.startswith(AOSP_PREFIX)): 2206 model = model[len(AOSP_PREFIX):] 2207 return model 2208 2209 2210def is_sms_match(event, phonenumber_tx, text): 2211 """Return True if 'text' equals to event['data']['Text'] 2212 and phone number match. 2213 2214 Args: 2215 event: Event object to verify. 2216 phonenumber_tx: phone number for sender. 2217 text: text string to verify. 2218 2219 Returns: 2220 Return True if 'text' equals to event['data']['Text'] 2221 and phone number match. 2222 """ 2223 return ( 2224 check_phone_number_match(event['data']['Sender'], phonenumber_tx) and 2225 event['data']['Text'] == text) 2226 2227 2228def is_sms_partial_match(event, phonenumber_tx, text): 2229 """Return True if 'text' starts with event['data']['Text'] 2230 and phone number match. 2231 2232 Args: 2233 event: Event object to verify. 2234 phonenumber_tx: phone number for sender. 2235 text: text string to verify. 2236 2237 Returns: 2238 Return True if 'text' starts with event['data']['Text'] 2239 and phone number match. 2240 """ 2241 return ( 2242 check_phone_number_match(event['data']['Sender'], phonenumber_tx) and 2243 text.startswith(event['data']['Text'])) 2244 2245 2246def sms_send_receive_verify(log, ad_tx, ad_rx, array_message): 2247 """Send SMS, receive SMS, and verify content and sender's number. 2248 2249 Send (several) SMS from droid_tx to droid_rx. 2250 Verify SMS is sent, delivered and received. 2251 Verify received content and sender's number are correct. 2252 2253 Args: 2254 log: Log object. 2255 ad_tx: Sender's Android Device Object 2256 ad_rx: Receiver's Android Device Object 2257 array_message: the array of message to send/receive 2258 """ 2259 subid_tx = get_outgoing_message_sub_id(ad_tx) 2260 subid_rx = get_incoming_message_sub_id(ad_rx) 2261 return sms_send_receive_verify_for_subscription( 2262 log, ad_tx, ad_rx, subid_tx, subid_rx, array_message) 2263 2264 2265def wait_for_matching_sms(log, 2266 ad_rx, 2267 phonenumber_tx, 2268 text, 2269 allow_multi_part_long_sms=True): 2270 """Wait for matching incoming SMS. 2271 2272 Args: 2273 log: Log object. 2274 ad_rx: Receiver's Android Device Object 2275 phonenumber_tx: Sender's phone number. 2276 text: SMS content string. 2277 allow_multi_part_long_sms: is long SMS allowed to be received as 2278 multiple short SMS. This is optional, default value is True. 2279 2280 Returns: 2281 True if matching incoming SMS is received. 2282 """ 2283 if not allow_multi_part_long_sms: 2284 try: 2285 ad_rx.ed.wait_for_event(EventSmsReceived, is_sms_match, 2286 MAX_WAIT_TIME_SMS_RECEIVE, phonenumber_tx, 2287 text) 2288 return True 2289 except Empty: 2290 log.error("No matched SMS received event.") 2291 return False 2292 else: 2293 try: 2294 received_sms = '' 2295 while (text != ''): 2296 event = ad_rx.ed.wait_for_event( 2297 EventSmsReceived, is_sms_partial_match, 2298 MAX_WAIT_TIME_SMS_RECEIVE, phonenumber_tx, text) 2299 text = text[len(event['data']['Text']):] 2300 received_sms += event['data']['Text'] 2301 return True 2302 except Empty: 2303 log.error("No matched SMS received event.") 2304 if received_sms != '': 2305 log.error("Only received partial matched SMS: {}".format( 2306 received_sms)) 2307 return False 2308 2309 2310def sms_send_receive_verify_for_subscription(log, ad_tx, ad_rx, subid_tx, 2311 subid_rx, array_message): 2312 """Send SMS, receive SMS, and verify content and sender's number. 2313 2314 Send (several) SMS from droid_tx to droid_rx. 2315 Verify SMS is sent, delivered and received. 2316 Verify received content and sender's number are correct. 2317 2318 Args: 2319 log: Log object. 2320 ad_tx: Sender's Android Device Object.. 2321 ad_rx: Receiver's Android Device Object. 2322 subid_tx: Sender's subsciption ID to be used for SMS 2323 subid_rx: Receiver's subsciption ID to be used for SMS 2324 array_message: the array of message to send/receive 2325 """ 2326 2327 phonenumber_tx = ad_tx.cfg['subscription'][subid_tx]['phone_num'] 2328 phonenumber_rx = ad_rx.cfg['subscription'][subid_rx]['phone_num'] 2329 for text in array_message: 2330 log.info("Sending SMS {} to {}, len: {}, content: {}.".format( 2331 phonenumber_tx, phonenumber_rx, len(text), text)) 2332 result = False 2333 ad_rx.ed.clear_all_events() 2334 ad_rx.droid.smsStartTrackingIncomingSmsMessage() 2335 try: 2336 ad_tx.droid.smsSendTextMessage(phonenumber_rx, text, True) 2337 2338 try: 2339 ad_tx.ed.pop_event(EventSmsSentSuccess, 2340 MAX_WAIT_TIME_SMS_SENT_SUCCESS) 2341 except Empty: 2342 log.error("No sent_success event.") 2343 return False 2344 2345 if not wait_for_matching_sms(log, 2346 ad_rx, 2347 phonenumber_tx, 2348 text, 2349 allow_multi_part_long_sms=True): 2350 return False 2351 finally: 2352 ad_rx.droid.smsStopTrackingIncomingSmsMessage() 2353 return True 2354 2355 2356def mms_send_receive_verify(log, ad_tx, ad_rx, array_message): 2357 """Send SMS, receive SMS, and verify content and sender's number. 2358 2359 Send (several) SMS from droid_tx to droid_rx. 2360 Verify SMS is sent, delivered and received. 2361 Verify received content and sender's number are correct. 2362 2363 Args: 2364 log: Log object. 2365 ad_tx: Sender's Android Device Object 2366 ad_rx: Receiver's Android Device Object 2367 array_message: the array of message to send/receive 2368 """ 2369 return mms_send_receive_verify_for_subscription( 2370 log, ad_tx, ad_rx, get_outgoing_message_sub_id(ad_tx), 2371 get_incoming_message_sub_id(ad_rx), array_message) 2372 2373 2374#TODO: b/21569494 This function is still a WIP and is disabled 2375def mms_send_receive_verify_for_subscription(log, ad_tx, ad_rx, subid_tx, 2376 subid_rx, array_payload): 2377 """Send SMS, receive SMS, and verify content and sender's number. 2378 2379 Send (several) SMS from droid_tx to droid_rx. 2380 Verify SMS is sent, delivered and received. 2381 Verify received content and sender's number are correct. 2382 2383 Args: 2384 log: Log object. 2385 ad_tx: Sender's Android Device Object.. 2386 ad_rx: Receiver's Android Device Object. 2387 subid_tx: Sender's subsciption ID to be used for SMS 2388 subid_rx: Receiver's subsciption ID to be used for SMS 2389 array_message: the array of message to send/receive 2390 """ 2391 2392 log.error("Function is non-working: b/21569494") 2393 return False 2394 2395 phonenumber_tx = ad_tx.cfg['subscription'][subid_tx]['phone_num'] 2396 phonenumber_rx = ad_rx.cfg['subscription'][subid_rx]['phone_num'] 2397 for subject, message, filename in array_payload: 2398 log.info("Sending MMS {} to {}, subject: {}, message: {}.".format( 2399 phonenumber_tx, phonenumber_rx, subject, message)) 2400 result = False 2401 ad_rx.ed.clear_all_events() 2402 ad_rx.droid.smsStartTrackingIncomingMmsMessage() 2403 ad_rx.droid.smsStartTrackingIncomingSmsMessage() 2404 try: 2405 ad_tx.droid.smsSendMultimediaMessage( 2406 phonenumber_rx, subject, message, phonenumber_tx, filename) 2407 2408 ad_tx.ed.pop_event(EventMmsSentSuccess, 2409 MAX_WAIT_TIME_SMS_SENT_SUCCESS) 2410 2411 start_time = time.time() 2412 remaining_time = MAX_WAIT_TIME_SMS_RECEIVE 2413 while remaining_time > 0: 2414 event = ad_rx.ed.pop_event(EventSmsReceived, remaining_time) 2415 if check_phone_number_match(event['data']['Sender'], 2416 phonenumber_tx): 2417 log.debug("Received SMS Indication") 2418 while remaining_time > 0: 2419 event = ad_rx.ed.pop_event(EventDataSmsReceived, 2420 remaining_time) 2421 if check_phone_number_match(event['data']['Sender'], 2422 phonenumber_tx): 2423 result = True 2424 break 2425 remaining_time = time.time() - start_time 2426 remaining_time = time.time() - start_time 2427 2428 if not result: 2429 log.info("Expected sender:" + phonenumber_tx) 2430 log.error("Received sender:" + event['data']['Sender']) 2431 log.error("Failed in verify receiving MMS.") 2432 return False 2433 finally: 2434 ad_rx.droid.smsStopTrackingIncomingSmsMessage() 2435 ad_rx.droid.smsStopTrackingIncomingMmsMessage() 2436 return True 2437 2438 2439def ensure_network_rat(log, 2440 ad, 2441 network_preference, 2442 rat_family, 2443 voice_or_data=None, 2444 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2445 toggle_apm_after_setting=False): 2446 """Ensure ad's current network is in expected rat_family. 2447 """ 2448 return ensure_network_rat_for_subscription( 2449 log, ad, ad.droid.subscriptionGetDefaultSubId(), network_preference, 2450 rat_family, voice_or_data, max_wait_time, toggle_apm_after_setting) 2451 2452 2453def ensure_network_rat_for_subscription( 2454 log, 2455 ad, 2456 sub_id, 2457 network_preference, 2458 rat_family, 2459 voice_or_data=None, 2460 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2461 toggle_apm_after_setting=False): 2462 """Ensure ad's current network is in expected rat_family. 2463 """ 2464 if not ad.droid.telephonySetPreferredNetworkTypesForSubscription( 2465 network_preference, sub_id): 2466 log.error("Set Preferred Networks failed.") 2467 return False 2468 if is_droid_in_rat_family_for_subscription(log, ad, sub_id, rat_family, 2469 voice_or_data): 2470 return True 2471 2472 if toggle_apm_after_setting: 2473 toggle_airplane_mode(log, ad, True) 2474 time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) 2475 toggle_airplane_mode(log, ad, False) 2476 2477 result = wait_for_network_rat_for_subscription( 2478 log, ad, sub_id, rat_family, max_wait_time, voice_or_data) 2479 2480 log.info( 2481 "End of ensure_network_rat_for_subscription for {}. " 2482 "Setting to {}, Expecting {} {}. Current: voice: {}(family: {}), " 2483 "data: {}(family: {})".format( 2484 ad.serial, network_preference, rat_family, voice_or_data, 2485 ad.droid.telephonyGetCurrentVoiceNetworkTypeForSubscription( 2486 sub_id), 2487 rat_family_from_rat( 2488 ad.droid.telephonyGetCurrentVoiceNetworkTypeForSubscription( 2489 sub_id)), 2490 ad.droid.telephonyGetCurrentDataNetworkTypeForSubscription( 2491 sub_id), rat_family_from_rat( 2492 ad.droid.telephonyGetCurrentDataNetworkTypeForSubscription( 2493 sub_id)))) 2494 return result 2495 2496 2497def ensure_network_preference(log, 2498 ad, 2499 network_preference, 2500 voice_or_data=None, 2501 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2502 toggle_apm_after_setting=False): 2503 """Ensure that current rat is within the device's preferred network rats. 2504 """ 2505 return ensure_network_preference_for_subscription( 2506 log, ad, ad.droid.subscriptionGetDefaultSubId(), network_preference, 2507 voice_or_data, max_wait_time, toggle_apm_after_setting) 2508 2509 2510def ensure_network_preference_for_subscription( 2511 log, 2512 ad, 2513 sub_id, 2514 network_preference, 2515 voice_or_data=None, 2516 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2517 toggle_apm_after_setting=False): 2518 """Ensure ad's network preference is <network_preference> for sub_id. 2519 """ 2520 rat_family_list = rat_families_for_network_preference(network_preference) 2521 if not ad.droid.telephonySetPreferredNetworkTypesForSubscription( 2522 network_preference, sub_id): 2523 log.error("Set Preferred Networks failed.") 2524 return False 2525 if is_droid_in_rat_family_list_for_subscription( 2526 log, ad, sub_id, rat_family_list, voice_or_data): 2527 return True 2528 2529 if toggle_apm_after_setting: 2530 toggle_airplane_mode(log, ad, True) 2531 time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) 2532 toggle_airplane_mode(log, ad, False) 2533 2534 result = wait_for_preferred_network_for_subscription( 2535 log, ad, sub_id, network_preference, max_wait_time, voice_or_data) 2536 2537 log.info( 2538 "End of ensure_network_preference_for_subscription for {}. " 2539 "Setting to {}, Expecting {} {}. Current: voice: {}(family: {}), " 2540 "data: {}(family: {})".format( 2541 ad.serial, network_preference, rat_family_list, voice_or_data, 2542 ad.droid.telephonyGetCurrentVoiceNetworkTypeForSubscription( 2543 sub_id), 2544 rat_family_from_rat( 2545 ad.droid.telephonyGetCurrentVoiceNetworkTypeForSubscription( 2546 sub_id)), 2547 ad.droid.telephonyGetCurrentDataNetworkTypeForSubscription( 2548 sub_id), rat_family_from_rat( 2549 ad.droid.telephonyGetCurrentDataNetworkTypeForSubscription( 2550 sub_id)))) 2551 return result 2552 2553 2554def ensure_network_generation(log, 2555 ad, 2556 generation, 2557 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2558 voice_or_data=None, 2559 toggle_apm_after_setting=False): 2560 """Ensure ad's network is <network generation> for default subscription ID. 2561 2562 Set preferred network generation to <generation>. 2563 Toggle ON/OFF airplane mode if necessary. 2564 Wait for ad in expected network type. 2565 """ 2566 return ensure_network_generation_for_subscription( 2567 log, ad, ad.droid.subscriptionGetDefaultSubId(), generation, 2568 max_wait_time, voice_or_data, toggle_apm_after_setting) 2569 2570 2571def ensure_network_generation_for_subscription( 2572 log, 2573 ad, 2574 sub_id, 2575 generation, 2576 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2577 voice_or_data=None, 2578 toggle_apm_after_setting=False): 2579 """Ensure ad's network is <network generation> for specified subscription ID. 2580 2581 Set preferred network generation to <generation>. 2582 Toggle ON/OFF airplane mode if necessary. 2583 Wait for ad in expected network type. 2584 """ 2585 if is_droid_in_network_generation_for_subscription( 2586 log, ad, sub_id, generation, voice_or_data): 2587 return True 2588 2589 operator = get_operator_name(log, ad, sub_id) 2590 try: 2591 network_preference = network_preference_for_generaton(generation, 2592 operator) 2593 rat_family = rat_family_for_generation(generation, operator) 2594 except KeyError: 2595 log.error("Failed to find a rat_family entry for " 2596 "PLMN: {}, operator:{}, generation: {}".format( 2597 ad.droid.telephonyGetSimOperatorForSubscription( 2598 sub_id), operator, generation)) 2599 return False 2600 2601 if not ad.droid.telephonySetPreferredNetworkTypesForSubscription( 2602 network_preference, sub_id): 2603 log.error("Set Preferred Networks failed.") 2604 return False 2605 2606 if toggle_apm_after_setting: 2607 toggle_airplane_mode(log, ad, True) 2608 time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) 2609 toggle_airplane_mode(log, ad, False) 2610 2611 result = wait_for_network_generation_for_subscription( 2612 log, ad, sub_id, generation, max_wait_time, voice_or_data) 2613 2614 log.info( 2615 "End of ensure_network_generation_for_subscription for {}. " 2616 "Setting to {}, Expecting {} {}. Current: voice: {}(family: {}), " 2617 "data: {}(family: {})".format( 2618 ad.serial, network_preference, generation, voice_or_data, 2619 ad.droid.telephonyGetCurrentVoiceNetworkTypeForSubscription( 2620 sub_id), 2621 rat_generation_from_rat( 2622 ad.droid.telephonyGetCurrentVoiceNetworkTypeForSubscription( 2623 sub_id)), 2624 ad.droid.telephonyGetCurrentDataNetworkTypeForSubscription( 2625 sub_id), rat_generation_from_rat( 2626 ad.droid.telephonyGetCurrentDataNetworkTypeForSubscription( 2627 sub_id)))) 2628 2629 return result 2630 2631 2632def wait_for_network_rat(log, 2633 ad, 2634 rat_family, 2635 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2636 voice_or_data=None): 2637 return wait_for_network_rat_for_subscription( 2638 log, ad, ad.droid.subscriptionGetDefaultSubId(), rat_family, 2639 max_wait_time, voice_or_data) 2640 2641 2642def wait_for_network_rat_for_subscription( 2643 log, 2644 ad, 2645 sub_id, 2646 rat_family, 2647 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2648 voice_or_data=None): 2649 return _wait_for_droid_in_state_for_subscription( 2650 log, ad, sub_id, max_wait_time, 2651 is_droid_in_rat_family_for_subscription, rat_family, voice_or_data) 2652 2653 2654def wait_for_not_network_rat(log, 2655 ad, 2656 rat_family, 2657 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2658 voice_or_data=None): 2659 return wait_for_not_network_rat_for_subscription( 2660 log, ad, ad.droid.subscriptionGetDefaultSubId(), rat_family, 2661 max_wait_time, voice_or_data) 2662 2663 2664def wait_for_not_network_rat_for_subscription( 2665 log, 2666 ad, 2667 sub_id, 2668 rat_family, 2669 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2670 voice_or_data=None): 2671 return _wait_for_droid_in_state_for_subscription( 2672 log, ad, sub_id, max_wait_time, 2673 lambda log, ad, sub_id, *args, **kwargs: not is_droid_in_rat_family_for_subscription(log, ad, sub_id, rat_family, voice_or_data)) 2674 2675 2676def wait_for_preferred_network(log, 2677 ad, 2678 network_preference, 2679 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2680 voice_or_data=None): 2681 return wait_for_preferred_network_for_subscription( 2682 log, ad, ad.droid.subscriptionGetDefaultSubId(), network_preference, 2683 max_wait_time, voice_or_data) 2684 2685 2686def wait_for_preferred_network_for_subscription( 2687 log, 2688 ad, 2689 sub_id, 2690 network_preference, 2691 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2692 voice_or_data=None): 2693 rat_family_list = rat_families_for_network_preference(network_preference) 2694 return _wait_for_droid_in_state_for_subscription( 2695 log, ad, sub_id, max_wait_time, 2696 is_droid_in_rat_family_list_for_subscription, rat_family_list, 2697 voice_or_data) 2698 2699 2700def wait_for_network_generation(log, 2701 ad, 2702 generation, 2703 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2704 voice_or_data=None): 2705 return wait_for_network_generation_for_subscription( 2706 log, ad, ad.droid.subscriptionGetDefaultSubId(), generation, 2707 max_wait_time, voice_or_data) 2708 2709 2710def wait_for_network_generation_for_subscription( 2711 log, 2712 ad, 2713 sub_id, 2714 generation, 2715 max_wait_time=MAX_WAIT_TIME_NW_SELECTION, 2716 voice_or_data=None): 2717 return _wait_for_droid_in_state_for_subscription( 2718 log, ad, sub_id, max_wait_time, 2719 is_droid_in_network_generation_for_subscription, generation, 2720 voice_or_data) 2721 2722 2723def is_droid_in_rat_family(log, ad, rat_family, voice_or_data=None): 2724 return is_droid_in_rat_family_for_subscription( 2725 log, ad, ad.droid.subscriptionGetDefaultSubId(), rat_family, 2726 voice_or_data) 2727 2728 2729def is_droid_in_rat_family_for_subscription(log, 2730 ad, 2731 sub_id, 2732 rat_family, 2733 voice_or_data=None): 2734 return is_droid_in_rat_family_list_for_subscription( 2735 log, ad, sub_id, [rat_family], voice_or_data) 2736 2737 2738def is_droid_in_rat_familiy_list(log, ad, rat_family_list, voice_or_data=None): 2739 return is_droid_in_rat_family_list_for_subscription( 2740 log, ad, ad.droid.subscriptionGetDefaultSubId(), rat_family_list, 2741 voice_or_data) 2742 2743 2744def is_droid_in_rat_family_list_for_subscription(log, 2745 ad, 2746 sub_id, 2747 rat_family_list, 2748 voice_or_data=None): 2749 service_list = [NETWORK_SERVICE_DATA, NETWORK_SERVICE_VOICE] 2750 if voice_or_data: 2751 service_list = [voice_or_data] 2752 2753 for service in service_list: 2754 nw_rat = get_network_rat_for_subscription(log, ad, sub_id, service) 2755 if nw_rat == RAT_UNKNOWN or not is_valid_rat(nw_rat): 2756 continue 2757 if rat_family_from_rat(nw_rat) in rat_family_list: 2758 return True 2759 return False 2760 2761 2762def is_droid_in_network_generation(log, ad, nw_gen, voice_or_data): 2763 """Checks if a droid in expected network generation ("2g", "3g" or "4g"). 2764 2765 Args: 2766 log: log object. 2767 ad: android device. 2768 nw_gen: expected generation "4g", "3g", "2g". 2769 voice_or_data: check voice network generation or data network generation 2770 This parameter is optional. If voice_or_data is None, then if 2771 either voice or data in expected generation, function will return True. 2772 2773 Returns: 2774 True if droid in expected network generation. Otherwise False. 2775 """ 2776 return is_droid_in_network_generation_for_subscription( 2777 log, ad, ad.droid.subscriptionGetDefaultSubId(), nw_gen, voice_or_data) 2778 2779 2780def is_droid_in_network_generation_for_subscription(log, ad, sub_id, nw_gen, 2781 voice_or_data): 2782 """Checks if a droid in expected network generation ("2g", "3g" or "4g"). 2783 2784 Args: 2785 log: log object. 2786 ad: android device. 2787 nw_gen: expected generation "4g", "3g", "2g". 2788 voice_or_data: check voice network generation or data network generation 2789 This parameter is optional. If voice_or_data is None, then if 2790 either voice or data in expected generation, function will return True. 2791 2792 Returns: 2793 True if droid in expected network generation. Otherwise False. 2794 """ 2795 service_list = [NETWORK_SERVICE_DATA, NETWORK_SERVICE_VOICE] 2796 2797 if voice_or_data: 2798 service_list = [voice_or_data] 2799 2800 for service in service_list: 2801 nw_rat = get_network_rat_for_subscription(log, ad, sub_id, service) 2802 2803 if nw_rat == RAT_UNKNOWN or not is_valid_rat(nw_rat): 2804 continue 2805 2806 if rat_generation_from_rat(nw_rat) == nw_gen: 2807 return True 2808 else: 2809 return False 2810 2811 return False 2812 2813 2814def get_network_rat(log, ad, voice_or_data): 2815 """Get current network type (Voice network type, or data network type) 2816 for default subscription id 2817 2818 Args: 2819 ad: Android Device Object 2820 voice_or_data: Input parameter indicating to get voice network type or 2821 data network type. 2822 2823 Returns: 2824 Current voice/data network type. 2825 """ 2826 return get_network_rat_for_subscription( 2827 log, ad, ad.droid.subscriptionGetDefaultSubId(), voice_or_data) 2828 2829 2830def get_network_rat_for_subscription(log, ad, sub_id, voice_or_data): 2831 """Get current network type (Voice network type, or data network type) 2832 for specified subscription id 2833 2834 Args: 2835 ad: Android Device Object 2836 sub_id: subscription ID 2837 voice_or_data: Input parameter indicating to get voice network type or 2838 data network type. 2839 2840 Returns: 2841 Current voice/data network type. 2842 """ 2843 if voice_or_data == NETWORK_SERVICE_VOICE: 2844 ret_val = ad.droid.telephonyGetCurrentVoiceNetworkTypeForSubscription( 2845 sub_id) 2846 elif voice_or_data == NETWORK_SERVICE_DATA: 2847 ret_val = ad.droid.telephonyGetCurrentDataNetworkTypeForSubscription( 2848 sub_id) 2849 else: 2850 ret_val = ad.droid.telephonyGetNetworkTypeForSubscription(sub_id) 2851 2852 if ret_val is None: 2853 log.error("get_network_rat(): Unexpected null return value") 2854 return RAT_UNKNOWN 2855 else: 2856 return ret_val 2857 2858 2859def get_network_gen(log, ad, voice_or_data): 2860 """Get current network generation string (Voice network type, or data network type) 2861 2862 Args: 2863 ad: Android Device Object 2864 voice_or_data: Input parameter indicating to get voice network generation 2865 or data network generation. 2866 2867 Returns: 2868 Current voice/data network generation. 2869 """ 2870 return get_network_gen_for_subscription( 2871 log, ad, ad.droid.subscriptionGetDefaultSubId(), voice_or_data) 2872 2873 2874def get_network_gen_for_subscription(log, ad, sub_id, voice_or_data): 2875 """Get current network generation string (Voice network type, or data network type) 2876 2877 Args: 2878 ad: Android Device Object 2879 voice_or_data: Input parameter indicating to get voice network generation 2880 or data network generation. 2881 2882 Returns: 2883 Current voice/data network generation. 2884 """ 2885 try: 2886 return rat_generation_from_rat(get_network_rat_for_subscription( 2887 log, ad, sub_id, voice_or_data)) 2888 except KeyError: 2889 log.error( 2890 "KeyError happened in get_network_gen, ad:{}, d/v: {}, rat: {}".format( 2891 ad.serial, voice_or_data, get_network_rat_for_subscription( 2892 log, ad, sub_id, voice_or_data))) 2893 return GEN_UNKNOWN 2894 2895 2896def check_voice_mail_count(log, ad, voice_mail_count_before, 2897 voice_mail_count_after): 2898 """function to check if voice mail count is correct after leaving a new voice message. 2899 """ 2900 return get_voice_mail_count_check_function(get_operator_name(log, ad))( 2901 voice_mail_count_before, voice_mail_count_after) 2902 2903 2904def get_voice_mail_number(log, ad): 2905 """function to get the voice mail number 2906 """ 2907 voice_mail_number = get_voice_mail_number_function(get_operator_name(log, 2908 ad))() 2909 if voice_mail_number is None: 2910 return get_phone_number(log, ad) 2911 return voice_mail_number 2912 2913 2914def ensure_phones_idle(log, 2915 ads, 2916 settling_time=WAIT_TIME_ANDROID_STATE_SETTLING): 2917 """Ensure ads idle (not in call). 2918 """ 2919 for ad in ads: 2920 if ad.droid.telecomIsInCall(): 2921 ad.droid.telecomEndCall() 2922 # Leave the delay time to make sure droid can recover to idle from ongoing call. 2923 time.sleep(settling_time) 2924 return True 2925 2926 2927def ensure_phone_idle(log, ad, settling_time=WAIT_TIME_ANDROID_STATE_SETTLING): 2928 """Ensure ad idle (not in call). 2929 """ 2930 return ensure_phones_idle(log, [ad], settling_time) 2931 2932 2933def ensure_phone_default_state(log, ad): 2934 """Ensure ad in default state. 2935 Phone not in call. 2936 Phone have no stored WiFi network and WiFi disconnected. 2937 Phone not in airplane mode. 2938 """ 2939 result = True 2940 if ad.droid.telecomIsInCall(): 2941 ad.droid.telecomEndCall() 2942 set_wfc_mode(log, ad, WFC_MODE_DISABLED) 2943 2944 if not wait_for_not_network_rat(log, 2945 ad, 2946 RAT_FAMILY_WLAN, 2947 voice_or_data=NETWORK_SERVICE_DATA): 2948 log.error( 2949 "ensure_phones_default_state: wait_for_droid_not_in iwlan fail {}.".format( 2950 ad.serial)) 2951 result = False 2952 if ((not WifiUtils.wifi_reset(log, ad)) or 2953 (not WifiUtils.wifi_toggle_state(log, ad, False))): 2954 log.error("ensure_phones_default_state:reset WiFi fail {}.".format( 2955 ad.serial)) 2956 result = False 2957 if not toggle_airplane_mode(log, ad, False): 2958 log.error( 2959 "ensure_phones_default_state:turn off airplane mode fail {}.".format( 2960 ad.serial)) 2961 result = False 2962 # make sure phone data is on 2963 ad.droid.telephonyToggleDataConnection(True) 2964 2965 # Leave the delay time to make sure droid can recover to idle from ongoing call. 2966 time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) 2967 return result 2968 2969 2970def ensure_phones_default_state(log, ads): 2971 """Ensure ads in default state. 2972 Phone not in call. 2973 Phone have no stored WiFi network and WiFi disconnected. 2974 Phone not in airplane mode. 2975 """ 2976 tasks = [] 2977 for ad in ads: 2978 tasks.append((ensure_phone_default_state, (log, ad))) 2979 if not multithread_func(log, tasks): 2980 log.error("Ensure_phones_default_state Fail.") 2981 return False 2982 return True 2983 2984 2985def ensure_wifi_connected(log, ad, wifi_ssid, wifi_pwd=None, retry=1): 2986 """Ensure ad connected to wifi. 2987 2988 Args: 2989 log: Log object. 2990 ad: Android device object. 2991 wifi_ssid: WiFi network SSID. 2992 wifi_pwd: WiFi network password. This is optional. 2993 2994 """ 2995 while (retry >= 0): 2996 WifiUtils.wifi_reset(log, ad) 2997 WifiUtils.wifi_toggle_state(log, ad, False) 2998 WifiUtils.wifi_toggle_state(log, ad, True) 2999 if WifiUtils.wifi_connect(log, ad, wifi_ssid, wifi_pwd): 3000 return True 3001 else: 3002 log.info("ensure_wifi_connected: Connect WiFi failed, retry + 1.") 3003 retry -= 1 3004 return False 3005 3006 3007def reset_preferred_network_type_to_allowable_range(log, ad): 3008 """If preferred network type is not in allowable range, reset to GEN_4G 3009 preferred network type. 3010 3011 Args: 3012 log: log object 3013 ad: android device object 3014 3015 Returns: 3016 None 3017 """ 3018 sub_info_list = ad.droid.subscriptionGetAllSubInfoList() 3019 for sub_info in sub_info_list: 3020 sub_id = sub_info['subscriptionId'] 3021 operator = get_operator_name(log, ad, sub_id) 3022 current_preference = \ 3023 ad.droid.telephonyGetPreferredNetworkTypesForSubscription(sub_id) 3024 try: 3025 if current_preference not in get_allowable_network_preference( 3026 operator): 3027 network_preference = network_preference_for_generaton(GEN_4G, 3028 operator) 3029 ad.droid.telephonySetPreferredNetworkTypesForSubscription( 3030 network_preference, sub_id) 3031 except KeyError: 3032 pass 3033 3034 3035def task_wrapper(task): 3036 """Task wrapper for multithread_func 3037 3038 Args: 3039 task[0]: function to be wrapped. 3040 task[1]: function args. 3041 3042 Returns: 3043 Return value of wrapped function call. 3044 """ 3045 func = task[0] 3046 params = task[1] 3047 return func(*params) 3048 3049 3050def multithread_func(log, tasks): 3051 """Multi-thread function wrapper. 3052 3053 Args: 3054 log: log object. 3055 tasks: tasks to be executed in parallel. 3056 3057 Returns: 3058 True if all tasks return True. 3059 False if any task return False. 3060 """ 3061 MAX_NUMBER_OF_WORKERS = 4 3062 number_of_workers = min(MAX_NUMBER_OF_WORKERS, len(tasks)) 3063 executor = concurrent.futures.ThreadPoolExecutor( 3064 max_workers=number_of_workers) 3065 results = list(executor.map(task_wrapper, tasks)) 3066 executor.shutdown() 3067 log.info("multithread_func result: {}".format(results)) 3068 for r in results: 3069 if not r: 3070 return False 3071 return True 3072 3073 3074def set_phone_screen_on(log, ad, screen_on_time=MAX_SCREEN_ON_TIME): 3075 """Set phone screen on time. 3076 3077 Args: 3078 log: Log object. 3079 ad: Android device object. 3080 screen_on_time: screen on time. 3081 This is optional, default value is MAX_SCREEN_ON_TIME. 3082 Returns: 3083 True if set successfully. 3084 """ 3085 ad.droid.setScreenTimeout(screen_on_time) 3086 return screen_on_time == ad.droid.getScreenTimeout() 3087 3088 3089def set_phone_silent_mode(log, ad, silent_mode=True): 3090 """Set phone silent mode. 3091 3092 Args: 3093 log: Log object. 3094 ad: Android device object. 3095 silent_mode: set phone silent or not. 3096 This is optional, default value is True (silent mode on). 3097 Returns: 3098 True if set successfully. 3099 """ 3100 ad.droid.toggleRingerSilentMode(silent_mode) 3101 return silent_mode == ad.droid.checkRingerSilentMode() 3102 3103 3104def set_preferred_subid_for_sms(log, ad, sub_id): 3105 """set subscription id for SMS 3106 3107 Args: 3108 log: Log object. 3109 ad: Android device object. 3110 sub_id :Subscription ID. 3111 3112 """ 3113 log.info("Setting subscription:{} as Message SIM for {}".format(sub_id, 3114 ad.serial)) 3115 ad.droid.subscriptionSetDefaultSmsSubId(sub_id) 3116 # Wait to make sure settings take effect 3117 time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) 3118 return sub_id == ad.droid.subscriptionGetDefaultSmsSubId() 3119 3120 3121def set_preferred_subid_for_data(log, ad, sub_id): 3122 """set subscription id for data 3123 3124 Args: 3125 log: Log object. 3126 ad: Android device object. 3127 sub_id :Subscription ID. 3128 3129 """ 3130 log.info("Setting subscription:{} as Data SIM for {}".format(sub_id, 3131 ad.serial)) 3132 ad.droid.subscriptionSetDefaultDataSubId(sub_id) 3133 time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) 3134 # Wait to make sure settings take effect 3135 # Data SIM change takes around 1 min 3136 # Check whether data has changed to selected sim 3137 if not wait_for_data_connection(log, ad, True, 3138 MAX_WAIT_TIME_DATA_SUB_CHANGE): 3139 log.error("Data Connection failed - Not able to switch Data SIM") 3140 return False 3141 return True 3142 3143 3144def set_preferred_subid_for_voice(log, ad, sub_id): 3145 """set subscription id for voice 3146 3147 Args: 3148 log: Log object. 3149 ad: Android device object. 3150 sub_id :Subscription ID. 3151 3152 """ 3153 log.info("Setting subscription:{} as Voice SIM for {}".format(sub_id, 3154 ad.serial)) 3155 ad.droid.subscriptionSetDefaultVoiceSubId(sub_id) 3156 ad.droid.telecomSetUserSelectedOutgoingPhoneAccountBySubId(sub_id) 3157 # Wait to make sure settings take effect 3158 time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) 3159 return True 3160 3161 3162def set_call_state_listen_level(log, ad, value, sub_id): 3163 """Set call state listen level for subscription id. 3164 3165 Args: 3166 log: Log object. 3167 ad: Android device object. 3168 value: True or False 3169 sub_id :Subscription ID. 3170 3171 Returns: 3172 True or False 3173 """ 3174 if sub_id == INVALID_SUB_ID: 3175 log.error("Invalid Subscription ID") 3176 return False 3177 ad.droid.telephonyAdjustPreciseCallStateListenLevelForSubscription( 3178 "Foreground", value, sub_id) 3179 ad.droid.telephonyAdjustPreciseCallStateListenLevelForSubscription( 3180 "Ringing", value, sub_id) 3181 ad.droid.telephonyAdjustPreciseCallStateListenLevelForSubscription( 3182 "Background", value, sub_id) 3183 return True 3184 3185 3186def setup_sim(log, ad, sub_id, voice=False, sms=False, data=False): 3187 """set subscription id for voice, sms and data 3188 3189 Args: 3190 log: Log object. 3191 ad: Android device object. 3192 sub_id :Subscription ID. 3193 voice: True if to set subscription as default voice subscription 3194 sms: True if to set subscription as default sms subscription 3195 data: True if to set subscription as default data subscription 3196 3197 """ 3198 if sub_id == INVALID_SUB_ID: 3199 log.error("Invalid Subscription ID") 3200 return False 3201 else: 3202 if voice: 3203 if not set_preferred_subid_for_voice(log, ad, sub_id): 3204 return False 3205 if sms: 3206 if not set_preferred_subid_for_sms(log, ad, sub_id): 3207 return False 3208 if data: 3209 if not set_preferred_subid_for_data(log, ad, sub_id): 3210 return False 3211 return True 3212 3213 3214def is_event_match(event, field, value): 3215 """Return if <field> in "event" match <value> or not. 3216 3217 Args: 3218 event: event to test. This event need to have <field>. 3219 field: field to match. 3220 value: value to match. 3221 3222 Returns: 3223 True if <field> in "event" match <value>. 3224 False otherwise. 3225 """ 3226 return is_event_match_for_list(event, field, [value]) 3227 3228 3229def is_event_match_for_list(event, field, value_list): 3230 """Return if <field> in "event" match any one of the value 3231 in "value_list" or not. 3232 3233 Args: 3234 event: event to test. This event need to have <field>. 3235 field: field to match. 3236 value_list: a list of value to match. 3237 3238 Returns: 3239 True if <field> in "event" match one of the value in "value_list". 3240 False otherwise. 3241 """ 3242 try: 3243 value_in_event = event['data'][field] 3244 except KeyError: 3245 return False 3246 for value in value_list: 3247 if value_in_event == value: 3248 return True 3249 return False 3250 3251 3252def is_network_call_back_event_match(event, network_callback_id, 3253 network_callback_event): 3254 try: 3255 return ((network_callback_id == event[ 3256 'data'][NetworkCallbackContainer.ID]) and 3257 (network_callback_event == event['data'][ 3258 NetworkCallbackContainer.NETWORK_CALLBACK_EVENT])) 3259 except KeyError: 3260 return False 3261 3262 3263def is_build_id(log, ad, build_id): 3264 """Return if ad's build id is the same as input parameter build_id. 3265 3266 Args: 3267 log: log object. 3268 ad: android device object. 3269 build_id: android build id. 3270 3271 Returns: 3272 True if ad's build id is the same as input parameter build_id. 3273 False otherwise. 3274 """ 3275 actual_bid = ad.droid.getBuildID() 3276 3277 log.info("{} BUILD DISPLAY: {}" 3278 .format(ad.serial, ad.droid.getBuildDisplay())) 3279 #In case we want to log more stuff/more granularity... 3280 #log.info("{} BUILD ID:{} ".format(ad.serial, ad.droid.getBuildID())) 3281 #log.info("{} BUILD FINGERPRINT: {} " 3282 # .format(ad.serial), ad.droid.getBuildFingerprint()) 3283 #log.info("{} BUILD TYPE: {} " 3284 # .format(ad.serial), ad.droid.getBuildType()) 3285 #log.info("{} BUILD NUMBER: {} " 3286 # .format(ad.serial), ad.droid.getBuildNumber()) 3287 if actual_bid.upper() != build_id.upper(): 3288 log.error("{}: Incorrect Build ID".format(ad.model)) 3289 return False 3290 return True 3291 3292 3293def is_uri_equivalent(uri1, uri2): 3294 """Check whether two input uris match or not. 3295 3296 Compare Uris. 3297 If Uris are tel URI, it will only take the digit part 3298 and compare as phone number. 3299 Else, it will just do string compare. 3300 3301 Args: 3302 uri1: 1st uri to be compared. 3303 uri2: 2nd uri to be compared. 3304 3305 Returns: 3306 True if two uris match. Otherwise False. 3307 """ 3308 3309 #If either is None/empty we return false 3310 if not uri1 or not uri2: 3311 return False 3312 3313 try: 3314 if uri1.startswith('tel:') and uri2.startswith('tel:'): 3315 uri1_number = get_number_from_tel_uri(uri1) 3316 uri2_number = get_number_from_tel_uri(uri2) 3317 return check_phone_number_match(uri1_number, uri2_number) 3318 else: 3319 return uri1 == uri2 3320 except AttributeError as e: 3321 return False 3322 3323 3324def get_call_uri(ad, call_id): 3325 """Get call's uri field. 3326 3327 Get Uri for call_id in ad. 3328 3329 Args: 3330 ad: android device object. 3331 call_id: the call id to get Uri from. 3332 3333 Returns: 3334 call's Uri if call is active and have uri field. None otherwise. 3335 """ 3336 try: 3337 call_detail = ad.droid.telecomCallGetDetails(call_id) 3338 return call_detail["Handle"]["Uri"] 3339 except: 3340 return None 3341 3342 3343def get_number_from_tel_uri(uri): 3344 """Get Uri number from tel uri 3345 3346 Args: 3347 uri: input uri 3348 3349 Returns: 3350 If input uri is tel uri, return the number part. 3351 else return None. 3352 """ 3353 if uri.startswith('tel:'): 3354 uri_number = ''.join(i for i in urllib.parse.unquote(uri) 3355 if i.isdigit()) 3356 return uri_number 3357 else: 3358 return None 3359 3360 3361# TODO: b/26294018 Remove wrapper class once wifi_utils methods updated 3362class WifiUtils(): 3363 3364 from acts.test_utils.wifi.wifi_test_utils \ 3365 import reset_wifi as _reset_wifi 3366 from acts.test_utils.wifi.wifi_test_utils \ 3367 import wifi_connect as _wifi_connect 3368 from acts.test_utils.wifi.wifi_test_utils \ 3369 import wifi_toggle_state as _wifi_toggle_state 3370 from acts.test_utils.wifi.wifi_test_utils \ 3371 import start_wifi_tethering as _start_wifi_tethering 3372 from acts.test_utils.wifi.wifi_test_utils \ 3373 import stop_wifi_tethering as _stop_wifi_tethering 3374 from acts.test_utils.wifi.wifi_test_utils \ 3375 import WifiEnums as _WifiEnums 3376 3377 WIFI_CONFIG_APBAND_2G = _WifiEnums.WIFI_CONFIG_APBAND_2G 3378 WIFI_CONFIG_APBAND_5G = _WifiEnums.WIFI_CONFIG_APBAND_5G 3379 SSID_KEY = _WifiEnums.SSID_KEY 3380 PWD_KEY = _WifiEnums.PWD_KEY 3381 3382 @staticmethod 3383 def wifi_toggle_state(log, ad, state): 3384 try: 3385 WifiUtils._wifi_toggle_state(ad, state) 3386 except Exception as e: 3387 log.error("WifiUtils.wifi_toggle_state exception: {}".format(e)) 3388 return False 3389 return True 3390 3391 @staticmethod 3392 def wifi_reset(log, ad, disable_wifi=True): 3393 try: 3394 WifiUtils._reset_wifi(ad) 3395 except Exception as e: 3396 log.error("WifiUtils.wifi_reset exception: {}".format(e)) 3397 return False 3398 finally: 3399 if disable_wifi is True: 3400 ad.droid.wifiToggleState(False) 3401 # Ensure toggle state has human-time to take effect 3402 time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) 3403 return True 3404 3405 @staticmethod 3406 def wifi_connect(log, ad, ssid, password=None): 3407 if password == "": 3408 password = None 3409 try: 3410 network = {WifiUtils.SSID_KEY: ssid} 3411 if password: 3412 network[WifiUtils.PWD_KEY] = password 3413 WifiUtils._wifi_connect(ad, network) 3414 except Empty: 3415 # did not get event, then check connection info 3416 try: 3417 if ad.droid.wifiGetConnectionInfo()[ 3418 WifiUtils.SSID_KEY] == ssid: 3419 return True 3420 else: 3421 log.error( 3422 "WifiUtils.wifi_connect not connected." 3423 "No event received. Expected SSID: {}, current SSID:{}".format( 3424 ssid, ad.droid.wifiGetConnectionInfo()[ 3425 WifiUtils.SSID_KEY])) 3426 return False 3427 except Exception as e: 3428 log.error("WifiUtils.wifi_connect not connected, no event.") 3429 return False 3430 except Exception as e: 3431 log.error("WifiUtils.wifi_connect exception: {}".format(e)) 3432 return False 3433 return True 3434 3435 @staticmethod 3436 def start_wifi_tethering(log, ad, ssid, password, ap_band=None): 3437 try: 3438 return WifiUtils._start_wifi_tethering(ad, ssid, password, ap_band) 3439 except Exception as e: 3440 log.error("WifiUtils.start_wifi_tethering exception: {}".format(e)) 3441 return False 3442 3443 @staticmethod 3444 def stop_wifi_tethering(log, ad): 3445 try: 3446 WifiUtils._stop_wifi_tethering(ad) 3447 return True 3448 except Exception as e: 3449 log.error("WifiUtils.stop_wifi_tethering exception: {}".format(e)) 3450 return False 3451