• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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