• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3#   Copyright 2021 - 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
17import re
18import time
19from queue import Empty
20from acts import signals
21from acts.logger import epoch_to_log_line_timestamp
22from acts.utils import get_current_epoch_time
23from acts_contrib.test_utils.tel.loggers.protos.telephony_metric_pb2 import TelephonyVoiceTestResult
24from acts_contrib.test_utils.tel.tel_defines import CarrierConfigs
25from acts_contrib.test_utils.tel.tel_defines import CARRIER_NTT_DOCOMO, CARRIER_KDDI, CARRIER_RAKUTEN, CARRIER_SBM
26from acts_contrib.test_utils.tel.tel_defines import CALL_PROPERTY_HIGH_DEF_AUDIO
27from acts_contrib.test_utils.tel.tel_defines import CALL_STATE_ACTIVE
28from acts_contrib.test_utils.tel.tel_defines import CALL_STATE_HOLDING
29from acts_contrib.test_utils.tel.tel_defines import CAPABILITY_VOLTE
30from acts_contrib.test_utils.tel.tel_defines import CAPABILITY_WFC
31from acts_contrib.test_utils.tel.tel_defines import DIRECTION_MOBILE_ORIGINATED
32from acts_contrib.test_utils.tel.tel_defines import GEN_2G
33from acts_contrib.test_utils.tel.tel_defines import GEN_3G
34from acts_contrib.test_utils.tel.tel_defines import INCALL_UI_DISPLAY_BACKGROUND
35from acts_contrib.test_utils.tel.tel_defines import INCALL_UI_DISPLAY_FOREGROUND
36from acts_contrib.test_utils.tel.tel_defines import INVALID_SUB_ID
37from acts_contrib.test_utils.tel.tel_defines import MAX_SAVED_VOICE_MAIL
38from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_ACCEPT_CALL_TO_OFFHOOK_EVENT
39from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_CALL_DROP
40from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_CALL_IDLE_EVENT
41from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_CALL_INITIATION
42from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_CALLEE_RINGING
43from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_TELECOM_RINGING
44from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_VOICE_MAIL_COUNT
45from acts_contrib.test_utils.tel.tel_defines import NETWORK_SERVICE_DATA
46from acts_contrib.test_utils.tel.tel_defines import NETWORK_SERVICE_VOICE
47from acts_contrib.test_utils.tel.tel_defines import RAT_1XRTT
48from acts_contrib.test_utils.tel.tel_defines import RAT_IWLAN
49from acts_contrib.test_utils.tel.tel_defines import RAT_LTE
50from acts_contrib.test_utils.tel.tel_defines import RAT_UMTS
51from acts_contrib.test_utils.tel.tel_defines import RAT_UNKNOWN
52from acts_contrib.test_utils.tel.tel_defines import TELEPHONY_STATE_IDLE
53from acts_contrib.test_utils.tel.tel_defines import TELEPHONY_STATE_OFFHOOK
54from acts_contrib.test_utils.tel.tel_defines import TELEPHONY_STATE_RINGING
55from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING
56from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_BETWEEN_REG_AND_CALL
57from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_BETWEEN_STATE_CHECK
58from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_IN_CALL
59from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_LEAVE_VOICE_MAIL
60from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_REJECT_CALL
61from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_VOICE_MAIL_SERVER_RESPONSE
62from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
63from acts_contrib.test_utils.tel.tel_defines import EventCallStateChanged
64from acts_contrib.test_utils.tel.tel_defines import EventMessageWaitingIndicatorChanged
65from acts_contrib.test_utils.tel.tel_defines import CallStateContainer
66from acts_contrib.test_utils.tel.tel_defines import MessageWaitingIndicatorContainer
67from acts_contrib.test_utils.tel.tel_ims_utils import is_wfc_enabled
68from acts_contrib.test_utils.tel.tel_ims_utils import toggle_volte
69from acts_contrib.test_utils.tel.tel_ims_utils import toggle_wfc
70from acts_contrib.test_utils.tel.tel_ims_utils import set_wfc_mode
71from acts_contrib.test_utils.tel.tel_ims_utils import wait_for_volte_enabled
72from acts_contrib.test_utils.tel.tel_ims_utils import wait_for_wfc_enabled
73from acts_contrib.test_utils.tel.tel_ims_utils import wait_for_wfc_disabled
74from acts_contrib.test_utils.tel.tel_lookup_tables import get_voice_mail_delete_digit
75from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phones_idle
76from acts_contrib.test_utils.tel.tel_phone_setup_utils import wait_for_network_rat
77from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phone_subscription
78from acts_contrib.test_utils.tel.tel_phone_setup_utils import wait_for_not_network_rat
79from acts_contrib.test_utils.tel.tel_phone_setup_utils import wait_for_voice_attach
80from acts_contrib.test_utils.tel.tel_subscription_utils import get_incoming_voice_sub_id
81from acts_contrib.test_utils.tel.tel_subscription_utils import get_outgoing_voice_sub_id
82from acts_contrib.test_utils.tel.tel_subscription_utils import set_subid_for_outgoing_call
83from acts_contrib.test_utils.tel.tel_subscription_utils import get_subid_from_slot_index
84from acts_contrib.test_utils.tel.tel_test_utils import _wait_for_droid_in_state
85from acts_contrib.test_utils.tel.tel_test_utils import check_call_state_connected_by_adb
86from acts_contrib.test_utils.tel.tel_test_utils import check_call_state_idle_by_adb
87from acts_contrib.test_utils.tel.tel_test_utils import check_phone_number_match
88from acts_contrib.test_utils.tel.tel_test_utils import check_voice_mail_count
89from acts_contrib.test_utils.tel.tel_test_utils import check_voice_network_type
90from acts_contrib.test_utils.tel.tel_test_utils import get_call_uri
91from acts_contrib.test_utils.tel.tel_test_utils import get_device_epoch_time
92from acts_contrib.test_utils.tel.tel_test_utils import get_network_gen_for_subscription
93from acts_contrib.test_utils.tel.tel_test_utils import get_network_rat
94from acts_contrib.test_utils.tel.tel_test_utils import get_network_rat_for_subscription
95from acts_contrib.test_utils.tel.tel_test_utils import get_number_from_tel_uri
96from acts_contrib.test_utils.tel.tel_test_utils import get_operator_name
97from acts_contrib.test_utils.tel.tel_test_utils import get_user_config_profile
98from acts_contrib.test_utils.tel.tel_test_utils import get_voice_mail_number
99from acts_contrib.test_utils.tel.tel_test_utils import is_event_match
100from acts_contrib.test_utils.tel.tel_test_utils import is_event_match_for_list
101from acts_contrib.test_utils.tel.tel_test_utils import num_active_calls
102from acts_contrib.test_utils.tel.tel_test_utils import TelResultWrapper
103from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode_by_adb
104from acts_contrib.test_utils.tel.tel_test_utils import verify_incall_state
105from acts_contrib.test_utils.tel.tel_test_utils import wait_for_state
106from acts_contrib.test_utils.tel.tel_wifi_utils import ensure_wifi_connected
107from acts_contrib.test_utils.tel.tel_wifi_utils import wifi_toggle_state
108
109CallResult = TelephonyVoiceTestResult.CallResult.Value
110result_dict ={}
111voice_call_type = {}
112
113
114def check_call_status(ad, voice_type_init=None, voice_type_in_call=None):
115    """"
116    Args:
117        ad: Android device object
118        voice_type_init: Voice network type before initiate call
119        voice_type_in_call: Voice network type in call state
120
121    Return:
122         voice_call_type_dict: Voice call status
123    """
124    dut = str(ad.serial)
125    network_type = voice_type_init + "_" + voice_type_in_call
126    if network_type == "NR_NR":
127        voice_call_type_dict = update_voice_call_type_dict(dut, "VoNR")
128    elif network_type == "NR_LTE":
129        voice_call_type_dict = update_voice_call_type_dict(dut, "EPSFB")
130    elif network_type == "LTE_LTE":
131        voice_call_type_dict = update_voice_call_type_dict(dut, "VoLTE")
132    elif network_type == "LTE_WCDMA":
133        voice_call_type_dict = update_voice_call_type_dict(dut, "CSFB")
134    else:
135        voice_call_type_dict = update_voice_call_type_dict(dut, "UNKNOWN")
136    return voice_call_type_dict
137
138
139def update_voice_call_type_dict(dut, key):
140    """
141    Args:
142        dut: Serial Number of android device object
143        key: Network subscription parameter (VoNR or EPSFB or VoLTE or CSFB or UNKNOWN)
144    Return:
145        voice_call_type: Voice call status
146    """
147    if dut in voice_call_type.keys():
148        voice_call_type[dut][key] += 1
149    else:
150        voice_call_type[dut] = {key:0}
151        voice_call_type[dut][key] += 1
152    return voice_call_type
153
154
155def dial_phone_number(ad, callee_number):
156    for number in str(callee_number):
157        if number == "#":
158            ad.send_keycode("POUND")
159        elif number == "*":
160            ad.send_keycode("STAR")
161        elif number in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]:
162            ad.send_keycode("%s" % number)
163
164
165def disconnect_call_by_id(log, ad, call_id):
166    """Disconnect call by call id.
167    """
168    ad.droid.telecomCallDisconnect(call_id)
169    return True
170
171
172def dumpsys_last_call_info(ad):
173    """ Get call information by dumpsys telecom. """
174    num = dumpsys_last_call_number(ad)
175    output = ad.adb.shell("dumpsys telecom")
176    result = re.search(r"Call TC@%s: {(.*?)}" % num, output, re.DOTALL)
177    call_info = {"TC": num}
178    if result:
179        result = result.group(1)
180        for attr in ("startTime", "endTime", "direction", "isInterrupted",
181                     "callTechnologies", "callTerminationsReason",
182                     "isVideoCall", "callProperties"):
183            match = re.search(r"%s: (.*)" % attr, result)
184            if match:
185                if attr in ("startTime", "endTime"):
186                    call_info[attr] = epoch_to_log_line_timestamp(
187                        int(match.group(1)))
188                else:
189                    call_info[attr] = match.group(1)
190    ad.log.debug("call_info = %s", call_info)
191    return call_info
192
193
194def dumpsys_last_call_number(ad):
195    output = ad.adb.shell("dumpsys telecom")
196    call_nums = re.findall("Call TC@(\d+):", output)
197    if not call_nums:
198        return 0
199    else:
200        return int(call_nums[-1])
201
202
203def dumpsys_new_call_info(ad, last_tc_number, retries=3, interval=5):
204    for i in range(retries):
205        if dumpsys_last_call_number(ad) > last_tc_number:
206            call_info = dumpsys_last_call_info(ad)
207            ad.log.info("New call info = %s", sorted(call_info.items()))
208            return call_info
209        else:
210            time.sleep(interval)
211    ad.log.error("New call is not in sysdump telecom")
212    return {}
213
214
215def emergency_dialer_call_by_keyevent(ad, callee_number):
216    for i in range(3):
217        if "EmergencyDialer" in ad.get_my_current_focus_window():
218            ad.log.info("EmergencyDialer is the current focus window")
219            break
220        elif i <= 2:
221            ad.adb.shell("am start -a com.android.phone.EmergencyDialer.DIAL")
222            time.sleep(1)
223        else:
224            ad.log.error("Unable to bring up EmergencyDialer")
225            return False
226    ad.log.info("Make a phone call to %s", callee_number)
227    dial_phone_number(ad, callee_number)
228    ad.send_keycode("CALL")
229
230
231def get_current_voice_rat(log, ad):
232    """Return current Voice RAT
233
234    Args:
235        ad: Android device object.
236    """
237    return get_current_voice_rat_for_subscription(
238        log, ad, get_outgoing_voice_sub_id(ad))
239
240
241def get_current_voice_rat_for_subscription(log, ad, sub_id):
242    """Return current Voice RAT for subscription id.
243
244    Args:
245        ad: Android device object.
246        sub_id: subscription id.
247    """
248    return get_network_rat_for_subscription(log, ad, sub_id,
249                                            NETWORK_SERVICE_VOICE)
250
251
252def hangup_call_by_adb(ad):
253    """Make emergency call by EmergencyDialer.
254
255    Args:
256        ad: Caller android device object.
257        callee_number: Callee phone number.
258    """
259    ad.log.info("End call by adb")
260    ad.send_keycode("ENDCALL")
261
262
263def hangup_call(log, ad, is_emergency=False):
264    """Hang up ongoing active call.
265
266    Args:
267        log: log object.
268        ad: android device object.
269
270    Returns:
271        True: if all calls are cleared
272        False: for errors
273    """
274    # short circuit in case no calls are active
275    if not ad.droid.telecomIsInCall():
276        ad.log.warning("No active call exists.")
277        return True
278    ad.ed.clear_events(EventCallStateChanged)
279    ad.droid.telephonyStartTrackingCallState()
280    ad.log.info("Hangup call.")
281    if is_emergency:
282        for call in ad.droid.telecomCallGetCallIds():
283            ad.droid.telecomCallDisconnect(call)
284    else:
285        ad.droid.telecomEndCall()
286
287    try:
288        ad.ed.wait_for_event(
289            EventCallStateChanged,
290            is_event_match,
291            timeout=MAX_WAIT_TIME_CALL_IDLE_EVENT,
292            field=CallStateContainer.CALL_STATE,
293            value=TELEPHONY_STATE_IDLE)
294    except Empty:
295        ad.log.warning("Call state IDLE event is not received after hang up.")
296    finally:
297        ad.droid.telephonyStopTrackingCallStateChange()
298    if not wait_for_state(ad.droid.telecomIsInCall, False, 15, 1):
299        ad.log.error("Telecom is in call, hangup call failed.")
300        return False
301    return True
302
303
304def initiate_emergency_dialer_call_by_adb(
305        log,
306        ad,
307        callee_number,
308        timeout=MAX_WAIT_TIME_CALL_INITIATION,
309        checking_interval=5):
310    """Make emergency call by EmergencyDialer.
311
312    Args:
313        ad: Caller android device object.
314        callee_number: Callee phone number.
315        emergency : specify the call is emergency.
316        Optional. Default value is False.
317
318    Returns:
319        result: if phone call is placed successfully.
320    """
321    try:
322        # Make a Call
323        ad.wakeup_screen()
324        ad.send_keycode("MENU")
325        ad.log.info("Call %s", callee_number)
326        ad.adb.shell("am start -a com.android.phone.EmergencyDialer.DIAL")
327        ad.adb.shell(
328            "am start -a android.intent.action.CALL_EMERGENCY -d tel:%s" %
329            callee_number)
330        if not timeout: return True
331        ad.log.info("Check call state")
332        # Verify Call State
333        elapsed_time = 0
334        while elapsed_time < timeout:
335            time.sleep(checking_interval)
336            elapsed_time += checking_interval
337            if check_call_state_connected_by_adb(ad):
338                ad.log.info("Call to %s is connected", callee_number)
339                return True
340            if check_call_state_idle_by_adb(ad):
341                ad.log.info("Call to %s failed", callee_number)
342                return False
343        ad.log.info("Make call to %s failed", callee_number)
344        return False
345    except Exception as e:
346        ad.log.error("initiate emergency call failed with error %s", e)
347
348
349def initiate_call(log,
350                  ad,
351                  callee_number,
352                  emergency=False,
353                  incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND,
354                  video=False):
355    """Make phone call from caller to callee.
356
357    Args:
358        ad_caller: Caller android device object.
359        callee_number: Callee phone number.
360        emergency : specify the call is emergency.
361            Optional. Default value is False.
362        incall_ui_display: show the dialer UI foreground or backgroud
363        video: whether to initiate as video call
364
365    Returns:
366        result: if phone call is placed successfully.
367    """
368    ad.ed.clear_events(EventCallStateChanged)
369    sub_id = get_outgoing_voice_sub_id(ad)
370    begin_time = get_device_epoch_time(ad)
371    ad.droid.telephonyStartTrackingCallStateForSubscription(sub_id)
372    try:
373        # Make a Call
374        ad.log.info("Make a phone call to %s", callee_number)
375        if emergency:
376            ad.droid.telecomCallEmergencyNumber(callee_number)
377        else:
378            ad.droid.telecomCallNumber(callee_number, video)
379
380        # Verify OFFHOOK state
381        if not wait_for_call_offhook_for_subscription(
382                log, ad, sub_id, event_tracking_started=True):
383            ad.log.info("sub_id %s not in call offhook state", sub_id)
384            last_call_drop_reason(ad, begin_time=begin_time)
385            return False
386        else:
387            return True
388
389    finally:
390        if hasattr(ad, "sdm_log") and getattr(ad, "sdm_log"):
391            ad.adb.shell("i2cset -fy 3 64 6 1 b", ignore_status=True)
392            ad.adb.shell("i2cset -fy 3 65 6 1 b", ignore_status=True)
393        ad.droid.telephonyStopTrackingCallStateChangeForSubscription(sub_id)
394
395        if incall_ui_display == INCALL_UI_DISPLAY_FOREGROUND:
396            ad.droid.telecomShowInCallScreen()
397        elif incall_ui_display == INCALL_UI_DISPLAY_BACKGROUND:
398            ad.droid.showHomeScreen()
399
400
401def last_call_drop_reason(ad, begin_time=None):
402    reasons = ad.search_logcat(
403        "qcril_qmi_voice_map_qmi_to_ril_last_call_failure_cause", begin_time)
404    reason_string = ""
405    if reasons:
406        log_msg = "Logcat call drop reasons:"
407        for reason in reasons:
408            log_msg = "%s\n\t%s" % (log_msg, reason["log_message"])
409            if "ril reason str" in reason["log_message"]:
410                reason_string = reason["log_message"].split(":")[-1].strip()
411        ad.log.info(log_msg)
412    reasons = ad.search_logcat("ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION",
413                               begin_time)
414    if reasons:
415        ad.log.warning("ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION is seen")
416    ad.log.info("last call dumpsys: %s",
417                sorted(dumpsys_last_call_info(ad).items()))
418    return reason_string
419
420
421def call_reject(log, ad_caller, ad_callee, reject=True):
422    """Caller call Callee, then reject on callee.
423
424
425    """
426    subid_caller = ad_caller.droid.subscriptionGetDefaultVoiceSubId()
427    subid_callee = ad_callee.incoming_voice_sub_id
428    ad_caller.log.info("Sub-ID Caller %s, Sub-ID Callee %s", subid_caller,
429                       subid_callee)
430    return call_reject_for_subscription(log, ad_caller, ad_callee,
431                                        subid_caller, subid_callee, reject)
432
433
434def call_reject_for_subscription(log,
435                                 ad_caller,
436                                 ad_callee,
437                                 subid_caller,
438                                 subid_callee,
439                                 reject=True):
440    """
441    """
442
443    caller_number = ad_caller.telephony['subscription'][subid_caller][
444        'phone_num']
445    callee_number = ad_callee.telephony['subscription'][subid_callee][
446        'phone_num']
447
448    ad_caller.log.info("Call from %s to %s", caller_number, callee_number)
449    if not initiate_call(log, ad_caller, callee_number):
450        ad_caller.log.error("Initiate call failed")
451        return False
452
453    if not wait_and_reject_call_for_subscription(
454            log, ad_callee, subid_callee, caller_number, WAIT_TIME_REJECT_CALL,
455            reject):
456        ad_callee.log.error("Reject call fail.")
457        return False
458    # Check if incoming call is cleared on callee or not.
459    if ad_callee.droid.telephonyGetCallStateForSubscription(
460            subid_callee) == TELEPHONY_STATE_RINGING:
461        ad_callee.log.error("Incoming call is not cleared")
462        return False
463    # Hangup on caller
464    hangup_call(log, ad_caller)
465    return True
466
467
468def call_reject_leave_message(log,
469                              ad_caller,
470                              ad_callee,
471                              verify_caller_func=None,
472                              wait_time_in_call=WAIT_TIME_LEAVE_VOICE_MAIL):
473    """On default voice subscription, Call from caller to callee,
474    reject on callee, caller leave a voice mail.
475
476    1. Caller call Callee.
477    2. Callee reject incoming call.
478    3. Caller leave a voice mail.
479    4. Verify callee received the voice mail notification.
480
481    Args:
482        ad_caller: caller android device object.
483        ad_callee: callee android device object.
484        verify_caller_func: function to verify caller is in correct state while in-call.
485            This is optional, default is None.
486        wait_time_in_call: time to wait when leaving a voice mail.
487            This is optional, default is WAIT_TIME_LEAVE_VOICE_MAIL
488
489    Returns:
490        True: if voice message is received on callee successfully.
491        False: for errors
492    """
493    subid_caller = get_outgoing_voice_sub_id(ad_caller)
494    subid_callee = get_incoming_voice_sub_id(ad_callee)
495    return call_reject_leave_message_for_subscription(
496        log, ad_caller, ad_callee, subid_caller, subid_callee,
497        verify_caller_func, wait_time_in_call)
498
499
500def check_reject_needed_for_voice_mail(log, ad_callee):
501    """Check if the carrier requires reject call to receive voice mail or just keep ringing
502    Requested in b//155935290
503    Four Japan carriers do not need to reject
504    SBM, KDDI, Ntt Docomo, Rakuten
505    Args:
506        log: log object
507        ad_callee: android device object
508    Returns:
509        True if callee's carrier is not one of the four Japan carriers
510        False if callee's carrier is one of the four Japan carriers
511    """
512
513    operators_no_reject = [CARRIER_NTT_DOCOMO,
514                           CARRIER_KDDI,
515                           CARRIER_RAKUTEN,
516                           CARRIER_SBM]
517    operator_name = get_operator_name(log, ad_callee)
518
519    return operator_name not in operators_no_reject
520
521
522def _is_on_message_waiting_event_true(event):
523    """Private function to return if the received EventMessageWaitingIndicatorChanged
524    event MessageWaitingIndicatorContainer.IS_MESSAGE_WAITING field is True.
525    """
526    return event['data'][MessageWaitingIndicatorContainer.IS_MESSAGE_WAITING]
527
528
529def call_reject_leave_message_for_subscription(
530        log,
531        ad_caller,
532        ad_callee,
533        subid_caller,
534        subid_callee,
535        verify_caller_func=None,
536        wait_time_in_call=WAIT_TIME_LEAVE_VOICE_MAIL):
537    """On specific voice subscription, Call from caller to callee,
538    reject on callee, caller leave a voice mail.
539
540    1. Caller call Callee.
541    2. Callee reject incoming call.
542    3. Caller leave a voice mail.
543    4. Verify callee received the voice mail notification.
544
545    Args:
546        ad_caller: caller android device object.
547        ad_callee: callee android device object.
548        subid_caller: caller's subscription id.
549        subid_callee: callee's subscription id.
550        verify_caller_func: function to verify caller is in correct state while in-call.
551            This is optional, default is None.
552        wait_time_in_call: time to wait when leaving a voice mail.
553            This is optional, default is WAIT_TIME_LEAVE_VOICE_MAIL
554
555    Returns:
556        True: if voice message is received on callee successfully.
557        False: for errors
558    """
559
560    # Currently this test utility only works for TMO and ATT and SPT.
561    # It does not work for VZW (see b/21559800)
562    # "with VVM TelephonyManager APIs won't work for vm"
563
564    caller_number = ad_caller.telephony['subscription'][subid_caller][
565        'phone_num']
566    callee_number = ad_callee.telephony['subscription'][subid_callee][
567        'phone_num']
568
569    ad_caller.log.info("Call from %s to %s", caller_number, callee_number)
570
571    try:
572        voice_mail_count_before = ad_callee.droid.telephonyGetVoiceMailCountForSubscription(
573            subid_callee)
574        ad_callee.log.info("voice mail count is %s", voice_mail_count_before)
575        # -1 means there are unread voice mail, but the count is unknown
576        # 0 means either this API not working (VZW) or no unread voice mail.
577        if voice_mail_count_before != 0:
578            log.warning("--Pending new Voice Mail, please clear on phone.--")
579
580        if not initiate_call(log, ad_caller, callee_number):
581            ad_caller.log.error("Initiate call failed.")
582            return False
583        if check_reject_needed_for_voice_mail(log, ad_callee):
584            carrier_specific_delay_reject = 30
585        else:
586            carrier_specific_delay_reject = 2
587        carrier_reject_call = not check_reject_needed_for_voice_mail(log, ad_callee)
588
589        if not wait_and_reject_call_for_subscription(
590                log, ad_callee, subid_callee, incoming_number=caller_number, delay_reject=carrier_specific_delay_reject,
591                reject=carrier_reject_call):
592            ad_callee.log.error("Reject call fail.")
593            return False
594
595        ad_callee.droid.telephonyStartTrackingVoiceMailStateChangeForSubscription(
596            subid_callee)
597
598        # ensure that all internal states are updated in telecom
599        time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING)
600        ad_callee.ed.clear_events(EventCallStateChanged)
601
602        if verify_caller_func and not verify_caller_func(log, ad_caller):
603            ad_caller.log.error("Caller not in correct state!")
604            return False
605
606        # TODO: b/26293512 Need to play some sound to leave message.
607        # Otherwise carrier voice mail server may drop this voice mail.
608        time.sleep(wait_time_in_call)
609
610        if not verify_caller_func:
611            caller_state_result = ad_caller.droid.telecomIsInCall()
612        else:
613            caller_state_result = verify_caller_func(log, ad_caller)
614        if not caller_state_result:
615            ad_caller.log.error("Caller not in correct state after %s seconds",
616                                wait_time_in_call)
617
618        if not hangup_call(log, ad_caller):
619            ad_caller.log.error("Error in Hanging-Up Call")
620            return False
621
622        ad_callee.log.info("Wait for voice mail indicator on callee.")
623        try:
624            event = ad_callee.ed.wait_for_event(
625                EventMessageWaitingIndicatorChanged,
626                _is_on_message_waiting_event_true)
627            ad_callee.log.info("Got event %s", event)
628        except Empty:
629            ad_callee.log.warning("No expected event %s",
630                                  EventMessageWaitingIndicatorChanged)
631            return False
632        voice_mail_count_after = ad_callee.droid.telephonyGetVoiceMailCountForSubscription(
633            subid_callee)
634        ad_callee.log.info(
635            "telephonyGetVoiceMailCount output - before: %s, after: %s",
636            voice_mail_count_before, voice_mail_count_after)
637
638        # voice_mail_count_after should:
639        # either equals to (voice_mail_count_before + 1) [For ATT and SPT]
640        # or equals to -1 [For TMO]
641        # -1 means there are unread voice mail, but the count is unknown
642        if not check_voice_mail_count(log, ad_callee, voice_mail_count_before,
643                                      voice_mail_count_after):
644            log.error("before and after voice mail count is not incorrect.")
645            return False
646    finally:
647        ad_callee.droid.telephonyStopTrackingVoiceMailStateChangeForSubscription(
648            subid_callee)
649    return True
650
651
652def call_voicemail_erase_all_pending_voicemail(log, ad):
653    """Script for phone to erase all pending voice mail.
654    This script only works for TMO and ATT and SPT currently.
655    This script only works if phone have already set up voice mail options,
656    and phone should disable password protection for voice mail.
657
658    1. If phone don't have pending voice message, return True.
659    2. Dial voice mail number.
660        For TMO, the number is '123'
661        For ATT, the number is phone's number
662        For SPT, the number is phone's number
663    3. Wait for voice mail connection setup.
664    4. Wait for voice mail play pending voice message.
665    5. Send DTMF to delete one message.
666        The digit is '7'.
667    6. Repeat steps 4 and 5 until voice mail server drop this call.
668        (No pending message)
669    6. Check telephonyGetVoiceMailCount result. it should be 0.
670
671    Args:
672        log: log object
673        ad: android device object
674    Returns:
675        False if error happens. True is succeed.
676    """
677    log.info("Erase all pending voice mail.")
678    count = ad.droid.telephonyGetVoiceMailCount()
679    if count == 0:
680        ad.log.info("No Pending voice mail.")
681        return True
682    if count == -1:
683        ad.log.info("There is pending voice mail, but the count is unknown")
684        count = MAX_SAVED_VOICE_MAIL
685    else:
686        ad.log.info("There are %s voicemails", count)
687
688    voice_mail_number = get_voice_mail_number(log, ad)
689    delete_digit = get_voice_mail_delete_digit(get_operator_name(log, ad))
690    if not initiate_call(log, ad, voice_mail_number):
691        log.error("Initiate call to voice mail failed.")
692        return False
693    time.sleep(WAIT_TIME_VOICE_MAIL_SERVER_RESPONSE)
694    callId = ad.droid.telecomCallGetCallIds()[0]
695    time.sleep(WAIT_TIME_VOICE_MAIL_SERVER_RESPONSE)
696    while (is_phone_in_call(log, ad) and (count > 0)):
697        ad.log.info("Press %s to delete voice mail.", delete_digit)
698        ad.droid.telecomCallPlayDtmfTone(callId, delete_digit)
699        ad.droid.telecomCallStopDtmfTone(callId)
700        time.sleep(WAIT_TIME_VOICE_MAIL_SERVER_RESPONSE)
701        count -= 1
702    if is_phone_in_call(log, ad):
703        hangup_call(log, ad)
704
705    # wait for telephonyGetVoiceMailCount to update correct result
706    remaining_time = MAX_WAIT_TIME_VOICE_MAIL_COUNT
707    while ((remaining_time > 0)
708           and (ad.droid.telephonyGetVoiceMailCount() != 0)):
709        time.sleep(1)
710        remaining_time -= 1
711    current_voice_mail_count = ad.droid.telephonyGetVoiceMailCount()
712    ad.log.info("telephonyGetVoiceMailCount: %s", current_voice_mail_count)
713    return (current_voice_mail_count == 0)
714
715
716def call_setup_teardown(log,
717                        ad_caller,
718                        ad_callee,
719                        ad_hangup=None,
720                        verify_caller_func=None,
721                        verify_callee_func=None,
722                        wait_time_in_call=WAIT_TIME_IN_CALL,
723                        incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND,
724                        dialing_number_length=None,
725                        video_state=None,
726                        slot_id_callee=None,
727                        voice_type_init=None,
728                        call_stats_check=False,
729                        result_info=result_dict):
730    """ Call process, including make a phone call from caller,
731    accept from callee, and hang up. The call is on default voice subscription
732
733    In call process, call from <droid_caller> to <droid_callee>,
734    accept the call, (optional)then hang up from <droid_hangup>.
735
736    Args:
737        ad_caller: Caller Android Device Object.
738        ad_callee: Callee Android Device Object.
739        ad_hangup: Android Device Object end the phone call.
740            Optional. Default value is None, and phone call will continue.
741        verify_call_mode_caller: func_ptr to verify caller in correct mode
742            Optional. Default is None
743        verify_call_mode_caller: func_ptr to verify caller in correct mode
744            Optional. Default is None
745        incall_ui_display: after answer the call, bring in-call UI to foreground or
746            background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND.
747            if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground.
748            if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background.
749            else, do nothing.
750        dialing_number_length: the number of digits used for dialing
751        slot_id_callee : the slot if of the callee to call to
752
753    Returns:
754        True if call process without any error.
755        False if error happened.
756
757    """
758    subid_caller = get_outgoing_voice_sub_id(ad_caller)
759    if slot_id_callee is None:
760        subid_callee = get_incoming_voice_sub_id(ad_callee)
761    else:
762        subid_callee = get_subid_from_slot_index(log, ad_callee, slot_id_callee)
763
764    return call_setup_teardown_for_subscription(
765        log, ad_caller, ad_callee, subid_caller, subid_callee, ad_hangup,
766        verify_caller_func, verify_callee_func, wait_time_in_call,
767        incall_ui_display, dialing_number_length, video_state,
768        voice_type_init, call_stats_check, result_info)
769
770
771def call_setup_teardown_for_subscription(
772        log,
773        ad_caller,
774        ad_callee,
775        subid_caller,
776        subid_callee,
777        ad_hangup=None,
778        verify_caller_func=None,
779        verify_callee_func=None,
780        wait_time_in_call=WAIT_TIME_IN_CALL,
781        incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND,
782        dialing_number_length=None,
783        video_state=None,
784        voice_type_init=None,
785        call_stats_check=False,
786        result_info=result_dict):
787    """ Call process, including make a phone call from caller,
788    accept from callee, and hang up. The call is on specified subscription
789
790    In call process, call from <droid_caller> to <droid_callee>,
791    accept the call, (optional)then hang up from <droid_hangup>.
792
793    Args:
794        ad_caller: Caller Android Device Object.
795        ad_callee: Callee Android Device Object.
796        subid_caller: Caller subscription ID
797        subid_callee: Callee subscription ID
798        ad_hangup: Android Device Object end the phone call.
799            Optional. Default value is None, and phone call will continue.
800        verify_call_mode_caller: func_ptr to verify caller in correct mode
801            Optional. Default is None
802        verify_call_mode_caller: func_ptr to verify caller in correct mode
803            Optional. Default is None
804        incall_ui_display: after answer the call, bring in-call UI to foreground or
805            background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND.
806            if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground.
807            if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background.
808            else, do nothing.
809
810    Returns:
811        TelResultWrapper which will evaluate as False if error.
812
813    """
814    CHECK_INTERVAL = 5
815    begin_time = get_current_epoch_time()
816    if not verify_caller_func:
817        verify_caller_func = is_phone_in_call
818    if not verify_callee_func:
819        verify_callee_func = is_phone_in_call
820
821    caller_number = ad_caller.telephony['subscription'][subid_caller][
822        'phone_num']
823    callee_number = ad_callee.telephony['subscription'][subid_callee][
824        'phone_num']
825
826    callee_number = truncate_phone_number(
827        log,
828        caller_number,
829        callee_number,
830        dialing_number_length)
831
832    tel_result_wrapper = TelResultWrapper(CallResult('SUCCESS'))
833    msg = "Call from %s to %s" % (caller_number, callee_number)
834    if video_state:
835        msg = "Video %s" % msg
836        video = True
837    else:
838        video = False
839    if ad_hangup:
840        msg = "%s for duration of %s seconds" % (msg, wait_time_in_call)
841    ad_caller.log.info(msg)
842
843    for ad in (ad_caller, ad_callee):
844        call_ids = ad.droid.telecomCallGetCallIds()
845        setattr(ad, "call_ids", call_ids)
846        if call_ids:
847            ad.log.info("Pre-exist CallId %s before making call", call_ids)
848
849    if not initiate_call(
850            log,
851            ad_caller,
852            callee_number,
853            incall_ui_display=incall_ui_display,
854            video=video):
855        ad_caller.log.error("Initiate call failed.")
856        tel_result_wrapper.result_value = CallResult('INITIATE_FAILED')
857        return tel_result_wrapper
858    else:
859        ad_caller.log.info("Caller initate call successfully")
860    if not wait_and_answer_call_for_subscription(
861            log,
862            ad_callee,
863            subid_callee,
864            incoming_number=caller_number,
865            caller=ad_caller,
866            incall_ui_display=incall_ui_display,
867            video_state=video_state):
868        ad_callee.log.error("Answer call fail.")
869        tel_result_wrapper.result_value = CallResult(
870            'NO_RING_EVENT_OR_ANSWER_FAILED')
871        return tel_result_wrapper
872    else:
873        ad_callee.log.info("Callee answered the call successfully")
874
875    for ad, call_func in zip([ad_caller, ad_callee],
876                                [verify_caller_func, verify_callee_func]):
877        call_ids = ad.droid.telecomCallGetCallIds()
878        new_call_ids = set(call_ids) - set(ad.call_ids)
879        if not new_call_ids:
880            ad.log.error(
881                "No new call ids are found after call establishment")
882            ad.log.error("telecomCallGetCallIds returns %s",
883                            ad.droid.telecomCallGetCallIds())
884            tel_result_wrapper.result_value = CallResult('NO_CALL_ID_FOUND')
885        for new_call_id in new_call_ids:
886            if not wait_for_in_call_active(ad, call_id=new_call_id):
887                tel_result_wrapper.result_value = CallResult(
888                    'CALL_STATE_NOT_ACTIVE_DURING_ESTABLISHMENT')
889            else:
890                ad.log.info("callProperties = %s",
891                            ad.droid.telecomCallGetProperties(new_call_id))
892
893        if not ad.droid.telecomCallGetAudioState():
894            ad.log.error("Audio is not in call state")
895            tel_result_wrapper.result_value = CallResult(
896                'AUDIO_STATE_NOT_INCALL_DURING_ESTABLISHMENT')
897
898        if call_func(log, ad):
899            ad.log.info("Call is in %s state", call_func.__name__)
900        else:
901            ad.log.error("Call is not in %s state, voice in RAT %s",
902                            call_func.__name__,
903                            ad.droid.telephonyGetCurrentVoiceNetworkType())
904            tel_result_wrapper.result_value = CallResult(
905                'CALL_DROP_OR_WRONG_STATE_DURING_ESTABLISHMENT')
906    if not tel_result_wrapper:
907        return tel_result_wrapper
908
909    if call_stats_check:
910        voice_type_in_call = check_voice_network_type([ad_caller, ad_callee], voice_init=False)
911        phone_a_call_type = check_call_status(ad_caller,
912                                                voice_type_init[0],
913                                                voice_type_in_call[0])
914        result_info["Call Stats"] = phone_a_call_type
915        ad_caller.log.debug("Voice Call Type: %s", phone_a_call_type)
916        phone_b_call_type = check_call_status(ad_callee,
917                                                voice_type_init[1],
918                                                voice_type_in_call[1])
919        result_info["Call Stats"] = phone_b_call_type
920        ad_callee.log.debug("Voice Call Type: %s", phone_b_call_type)
921
922    return wait_for_call_end(
923        log,
924        ad_caller,
925        ad_callee,
926        ad_hangup,
927        verify_caller_func,
928        verify_callee_func,
929        begin_time,
930        check_interval=CHECK_INTERVAL,
931        tel_result_wrapper=TelResultWrapper(CallResult('SUCCESS')),
932        wait_time_in_call=wait_time_in_call)
933
934
935def two_phone_call_leave_voice_mail(
936        log,
937        caller,
938        caller_idle_func,
939        caller_in_call_check_func,
940        callee,
941        callee_idle_func,
942        wait_time_in_call=WAIT_TIME_LEAVE_VOICE_MAIL):
943    """Call from caller to callee, reject on callee, caller leave a voice mail.
944
945    1. Caller call Callee.
946    2. Callee reject incoming call.
947    3. Caller leave a voice mail.
948    4. Verify callee received the voice mail notification.
949
950    Args:
951        caller: caller android device object.
952        caller_idle_func: function to check caller's idle state.
953        caller_in_call_check_func: function to check caller's in-call state.
954        callee: callee android device object.
955        callee_idle_func: function to check callee's idle state.
956        wait_time_in_call: time to wait when leaving a voice mail.
957            This is optional, default is WAIT_TIME_LEAVE_VOICE_MAIL
958
959    Returns:
960        True: if voice message is received on callee successfully.
961        False: for errors
962    """
963
964    ads = [caller, callee]
965
966    # Make sure phones are idle.
967    ensure_phones_idle(log, ads)
968    if caller_idle_func and not caller_idle_func(log, caller):
969        caller.log.error("Caller Failed to Reselect")
970        return False
971    if callee_idle_func and not callee_idle_func(log, callee):
972        callee.log.error("Callee Failed to Reselect")
973        return False
974
975    # TODO: b/26337871 Need to use proper API to check phone registered.
976    time.sleep(WAIT_TIME_BETWEEN_REG_AND_CALL)
977
978    # Make call and leave a message.
979    if not call_reject_leave_message(
980            log, caller, callee, caller_in_call_check_func, wait_time_in_call):
981        log.error("make a call and leave a message failed.")
982        return False
983    return True
984
985
986def two_phone_call_short_seq(log,
987                             phone_a,
988                             phone_a_idle_func,
989                             phone_a_in_call_check_func,
990                             phone_b,
991                             phone_b_idle_func,
992                             phone_b_in_call_check_func,
993                             call_sequence_func=None,
994                             wait_time_in_call=WAIT_TIME_IN_CALL,
995                             call_params=None):
996    """Call process short sequence.
997    1. Ensure phone idle and in idle_func check return True.
998    2. Call from PhoneA to PhoneB, accept on PhoneB.
999    3. Check phone state, hangup on PhoneA.
1000    4. Ensure phone idle and in idle_func check return True.
1001    5. Call from PhoneA to PhoneB, accept on PhoneB.
1002    6. Check phone state, hangup on PhoneB.
1003
1004    Args:
1005        phone_a: PhoneA's android device object.
1006        phone_a_idle_func: function to check PhoneA's idle state.
1007        phone_a_in_call_check_func: function to check PhoneA's in-call state.
1008        phone_b: PhoneB's android device object.
1009        phone_b_idle_func: function to check PhoneB's idle state.
1010        phone_b_in_call_check_func: function to check PhoneB's in-call state.
1011        call_sequence_func: default parameter, not implemented.
1012        wait_time_in_call: time to wait in call.
1013            This is optional, default is WAIT_TIME_IN_CALL
1014        call_params: list of call parameters for both MO/MT devices, including:
1015            - MO device object
1016            - MT device object
1017            - Device object hanging up the call
1018            - Function to check the in-call state of MO device
1019            - Function to check the in-call state of MT device
1020
1021            and the format should be:
1022            [(Args for the 1st call), (Args for the 2nd call), ......]
1023
1024            The format of args for each call should be:
1025            (mo_device_obj, mt_device_obj, device_obj_hanging_up,
1026            mo_in_call_check_func, mt_in_call_check_func)
1027
1028            Example of a call, which will not be hung up:
1029
1030            call_params = [
1031                (ads[0], ads[1], None, mo_in_call_check_func,
1032                mt_in_call_check_func)
1033            ]
1034
1035    Returns:
1036        TelResultWrapper which will evaluate as False if error.
1037    """
1038    ads = [phone_a, phone_b]
1039
1040    if not call_params:
1041        call_params = [
1042            (ads[0], ads[1], ads[0], phone_a_in_call_check_func,
1043            phone_b_in_call_check_func),
1044            (ads[0], ads[1], ads[1], phone_a_in_call_check_func,
1045            phone_b_in_call_check_func),
1046        ]
1047
1048    tel_result = TelResultWrapper(CallResult('SUCCESS'))
1049    for param in call_params:
1050        # Make sure phones are idle.
1051        ensure_phones_idle(log, ads)
1052        if phone_a_idle_func and not phone_a_idle_func(log, phone_a):
1053            phone_a.log.error("Phone A Failed to Reselect")
1054            return TelResultWrapper(CallResult('CALL_SETUP_FAILURE'))
1055        if phone_b_idle_func and not phone_b_idle_func(log, phone_b):
1056            phone_b.log.error("Phone B Failed to Reselect")
1057            return TelResultWrapper(CallResult('CALL_SETUP_FAILURE'))
1058
1059        # TODO: b/26337871 Need to use proper API to check phone registered.
1060        time.sleep(WAIT_TIME_BETWEEN_REG_AND_CALL)
1061
1062        # Make call.
1063        log.info("---> Call test: %s to %s <---", param[0].serial,
1064                 param[1].serial)
1065        tel_result = call_setup_teardown(
1066                log, *param, wait_time_in_call=wait_time_in_call)
1067        if not tel_result:
1068            log.error("Call Iteration Failed")
1069            break
1070
1071    return tel_result
1072
1073def two_phone_call_msim_short_seq(log,
1074                             phone_a,
1075                             phone_a_idle_func,
1076                             phone_a_in_call_check_func,
1077                             phone_b,
1078                             phone_b_idle_func,
1079                             phone_b_in_call_check_func,
1080                             call_sequence_func=None,
1081                             wait_time_in_call=WAIT_TIME_IN_CALL):
1082    """Call process short sequence.
1083    1. Ensure phone idle and in idle_func check return True.
1084    2. Call from PhoneA to PhoneB, accept on PhoneB.
1085    3. Check phone state, hangup on PhoneA.
1086    4. Ensure phone idle and in idle_func check return True.
1087    5. Call from PhoneA to PhoneB, accept on PhoneB.
1088    6. Check phone state, hangup on PhoneB.
1089    Args:
1090        phone_a: PhoneA's android device object.
1091        phone_a_idle_func: function to check PhoneA's idle state.
1092        phone_a_in_call_check_func: function to check PhoneA's in-call state.
1093        phone_b: PhoneB's android device object.
1094        phone_b_idle_func: function to check PhoneB's idle state.
1095        phone_b_in_call_check_func: function to check PhoneB's in-call state.
1096        call_sequence_func: default parameter, not implemented.
1097        wait_time_in_call: time to wait in call.
1098            This is optional, default is WAIT_TIME_IN_CALL
1099    Returns:
1100        True: if call sequence succeed.
1101        False: for errors
1102    """
1103    ads = [phone_a, phone_b]
1104    call_params = [
1105        (ads[0], ads[1], ads[0], phone_a_in_call_check_func,
1106         phone_b_in_call_check_func),
1107        (ads[0], ads[1], ads[1], phone_a_in_call_check_func,
1108         phone_b_in_call_check_func),
1109    ]
1110    for param in call_params:
1111        # Make sure phones are idle.
1112        ensure_phones_idle(log, ads)
1113        if phone_a_idle_func and not phone_a_idle_func(log, phone_a):
1114            phone_a.log.error("Phone A Failed to Reselect")
1115            return False
1116        if phone_b_idle_func and not phone_b_idle_func(log, phone_b):
1117            phone_b.log.error("Phone B Failed to Reselect")
1118            return False
1119        # TODO: b/26337871 Need to use proper API to check phone registered.
1120        time.sleep(WAIT_TIME_BETWEEN_REG_AND_CALL)
1121        # Make call.
1122        log.info("--> Call test: %s to %s <--", phone_a.serial, phone_b.serial)
1123        slots = 2
1124        for slot in range(slots):
1125            set_subid_for_outgoing_call(
1126                            ads[0], get_subid_from_slot_index(log,ads[0],slot))
1127            set_subid_for_outgoing_call(
1128                            ads[1], get_subid_from_slot_index(log,ads[1],slot))
1129            time.sleep(WAIT_TIME_BETWEEN_REG_AND_CALL)
1130            if not call_setup_teardown(log, *param,slot_id_callee = slot,
1131                                       wait_time_in_call=wait_time_in_call):
1132                log.error("Call Iteration Failed")
1133                return False
1134            if not call_setup_teardown(log, *param,slot_id_callee = 1-slot,
1135                                       wait_time_in_call=wait_time_in_call):
1136                log.error("Call Iteration Failed")
1137                return False
1138    return True
1139
1140def two_phone_call_long_seq(log,
1141                            phone_a,
1142                            phone_a_idle_func,
1143                            phone_a_in_call_check_func,
1144                            phone_b,
1145                            phone_b_idle_func,
1146                            phone_b_in_call_check_func,
1147                            call_sequence_func=None,
1148                            wait_time_in_call=WAIT_TIME_IN_CALL):
1149    """Call process long sequence.
1150    1. Ensure phone idle and in idle_func check return True.
1151    2. Call from PhoneA to PhoneB, accept on PhoneB.
1152    3. Check phone state, hangup on PhoneA.
1153    4. Ensure phone idle and in idle_func check return True.
1154    5. Call from PhoneA to PhoneB, accept on PhoneB.
1155    6. Check phone state, hangup on PhoneB.
1156    7. Ensure phone idle and in idle_func check return True.
1157    8. Call from PhoneB to PhoneA, accept on PhoneA.
1158    9. Check phone state, hangup on PhoneA.
1159    10. Ensure phone idle and in idle_func check return True.
1160    11. Call from PhoneB to PhoneA, accept on PhoneA.
1161    12. Check phone state, hangup on PhoneB.
1162
1163    Args:
1164        phone_a: PhoneA's android device object.
1165        phone_a_idle_func: function to check PhoneA's idle state.
1166        phone_a_in_call_check_func: function to check PhoneA's in-call state.
1167        phone_b: PhoneB's android device object.
1168        phone_b_idle_func: function to check PhoneB's idle state.
1169        phone_b_in_call_check_func: function to check PhoneB's in-call state.
1170        call_sequence_func: default parameter, not implemented.
1171        wait_time_in_call: time to wait in call.
1172            This is optional, default is WAIT_TIME_IN_CALL
1173
1174    Returns:
1175        TelResultWrapper which will evaluate as False if error.
1176
1177    """
1178    ads = [phone_a, phone_b]
1179
1180    call_params = [
1181        (ads[0], ads[1], ads[0], phone_a_in_call_check_func,
1182         phone_b_in_call_check_func),
1183        (ads[0], ads[1], ads[1], phone_a_in_call_check_func,
1184         phone_b_in_call_check_func),
1185        (ads[1], ads[0], ads[0], phone_b_in_call_check_func,
1186         phone_a_in_call_check_func),
1187        (ads[1], ads[0], ads[1], phone_b_in_call_check_func,
1188         phone_a_in_call_check_func),
1189    ]
1190
1191    tel_result = TelResultWrapper(CallResult('SUCCESS'))
1192    for param in call_params:
1193        # Make sure phones are idle.
1194        ensure_phones_idle(log, ads)
1195        if phone_a_idle_func and not phone_a_idle_func(log, phone_a):
1196            phone_a.log.error("Phone A Failed to Reselect")
1197            return TelResultWrapper(CallResult('CALL_SETUP_FAILURE'))
1198        if phone_b_idle_func and not phone_b_idle_func(log, phone_b):
1199            phone_b.log.error("Phone B Failed to Reselect")
1200            return TelResultWrapper(CallResult('CALL_SETUP_FAILURE'))
1201
1202        # TODO: b/26337871 Need to use proper API to check phone registered.
1203        time.sleep(WAIT_TIME_BETWEEN_REG_AND_CALL)
1204
1205        # Make call.
1206        log.info("---> Call test: %s to %s <---", param[0].serial,
1207                 param[1].serial)
1208        tel_result = call_setup_teardown(
1209                log, *param, wait_time_in_call=wait_time_in_call)
1210        if not tel_result:
1211            log.error("Call Iteration Failed")
1212            break
1213
1214    return tel_result
1215
1216def two_phone_call_msim_for_slot(log,
1217                             phone_a,
1218                             phone_a_slot,
1219                             phone_a_idle_func,
1220                             phone_a_in_call_check_func,
1221                             phone_b,
1222                             phone_b_slot,
1223                             phone_b_idle_func,
1224                             phone_b_in_call_check_func,
1225                             call_sequence_func=None,
1226                             wait_time_in_call=WAIT_TIME_IN_CALL,
1227                             retry=2):
1228    """Call process between 2 phones with specific slot.
1229    1. Ensure phone idle and in idle_func    check return True.
1230    2. Call from PhoneA to PhoneB, accept on PhoneB.
1231    3. Check phone state, hangup on PhoneA.
1232    4. Ensure phone idle and in idle_func check return True.
1233    5. Call from PhoneA to PhoneB, accept on PhoneB.
1234    6. Check phone state, hangup on PhoneB.
1235
1236    Args:
1237        phone_a: PhoneA's android device object.
1238        phone_a_slot: 0 or 1 (pSIM or eSIM)
1239        phone_a_idle_func: function to check PhoneA's idle state.
1240        phone_a_in_call_check_func: function to check PhoneA's in-call state.
1241        phone_b: PhoneB's android device object.
1242        phone_b_slot: 0 or 1 (pSIM or eSIM)
1243        phone_b_idle_func: function to check PhoneB's idle state.
1244        phone_b_in_call_check_func: function to check PhoneB's in-call state.
1245        call_sequence_func: default parameter, not implemented.
1246        wait_time_in_call: time to wait in call.
1247            This is optional, default is WAIT_TIME_IN_CALL
1248        retry: times of retry if call_setup_teardown failed.
1249
1250    Returns:
1251        True: if call sequence succeed.
1252        False: for errors
1253    """
1254    ads = [phone_a, phone_b]
1255
1256    call_params = [
1257        (ads[0], ads[1], ads[0], phone_a_in_call_check_func,
1258         phone_b_in_call_check_func),
1259        (ads[0], ads[1], ads[1], phone_a_in_call_check_func,
1260         phone_b_in_call_check_func),
1261    ]
1262
1263    tel_result = TelResultWrapper(CallResult('SUCCESS'))
1264    for param in call_params:
1265        # Make sure phones are idle.
1266        ensure_phones_idle(log, ads)
1267        if phone_a_idle_func and not phone_a_idle_func(log, phone_a):
1268            phone_a.log.error("Phone A Failed to Reselect")
1269            return TelResultWrapper(CallResult('CALL_SETUP_FAILURE'))
1270        if phone_b_idle_func and not phone_b_idle_func(log, phone_b):
1271            phone_b.log.error("Phone B Failed to Reselect")
1272            return TelResultWrapper(CallResult('CALL_SETUP_FAILURE'))
1273
1274        # TODO: b/26337871 Need to use proper API to check phone registered.
1275        time.sleep(WAIT_TIME_BETWEEN_REG_AND_CALL)
1276
1277        # Make call.
1278        log.info("--> Call test: %s slot %s to %s slot %s <--", phone_a.serial,
1279            phone_a_slot, phone_b.serial, phone_b_slot)
1280
1281        mo_default_voice_subid = get_subid_from_slot_index(log,ads[0],
1282            phone_a_slot)
1283        if mo_default_voice_subid == INVALID_SUB_ID:
1284            log.warning("Sub ID of MO (%s) slot %s is invalid.", phone_a.serial,
1285                phone_a_slot)
1286            return TelResultWrapper(CallResult('CALL_SETUP_FAILURE'))
1287        set_subid_for_outgoing_call(
1288                            ads[0], mo_default_voice_subid)
1289
1290        mt_default_voice_subid = get_subid_from_slot_index(log,ads[1],
1291            phone_b_slot)
1292        if mt_default_voice_subid == INVALID_SUB_ID:
1293            log.warning("Sub ID of MT (%s) slot %s is invalid.", phone_b.serial,
1294                phone_b_slot)
1295            return TelResultWrapper(CallResult('CALL_SETUP_FAILURE'))
1296
1297        tel_result = call_setup_teardown(
1298            log,
1299            *param,
1300            slot_id_callee=phone_b_slot,
1301            wait_time_in_call=wait_time_in_call)
1302
1303        while not tel_result:
1304            if retry <= 0:
1305                log.error("Call Iteration failed.")
1306                break
1307            else:
1308                log.info("RERUN call_setup_teardown.")
1309                tel_result = call_setup_teardown(
1310                    log,
1311                    *param,
1312                    slot_id_callee=phone_b_slot,
1313                    wait_time_in_call=wait_time_in_call)
1314
1315            retry = retry - 1
1316
1317    return tel_result
1318
1319
1320def is_phone_in_call(log, ad):
1321    """Return True if phone in call.
1322
1323    Args:
1324        log: log object.
1325        ad:  android device.
1326    """
1327    try:
1328        return ad.droid.telecomIsInCall()
1329    except:
1330        return "mCallState=2" in ad.adb.shell(
1331            "dumpsys telephony.registry | grep mCallState")
1332
1333
1334def is_phone_in_call_active(ad, call_id=None):
1335    """Return True if phone in active call.
1336
1337    Args:
1338        log: log object.
1339        ad:  android device.
1340        call_id: the call id
1341    """
1342    if ad.droid.telecomIsInCall():
1343        if not call_id:
1344            call_id = ad.droid.telecomCallGetCallIds()[0]
1345        call_state = ad.droid.telecomCallGetCallState(call_id)
1346        ad.log.info("%s state is %s", call_id, call_state)
1347        return call_state == "ACTIVE"
1348    else:
1349        ad.log.info("Not in telecomIsInCall")
1350        return False
1351
1352
1353def is_phone_in_call_volte(log, ad):
1354    """Return if phone is in VoLTE call.
1355
1356    Args:
1357        ad: Android device object.
1358    """
1359    return is_phone_in_call_volte_for_subscription(
1360        log, ad, get_outgoing_voice_sub_id(ad))
1361
1362
1363def is_phone_in_call_volte_for_subscription(log, ad, sub_id):
1364    """Return if phone is in VoLTE call for subscription id.
1365
1366    Args:
1367        ad: Android device object.
1368        sub_id: subscription id.
1369    """
1370    if not ad.droid.telecomIsInCall():
1371        ad.log.error("Not in call.")
1372        return False
1373    nw_type = get_network_rat_for_subscription(log, ad, sub_id,
1374                                               NETWORK_SERVICE_VOICE)
1375    if nw_type != RAT_LTE:
1376        ad.log.error("Voice rat on: %s. Expected: LTE", nw_type)
1377        return False
1378    return True
1379
1380
1381def is_phone_in_call_csfb(log, ad):
1382    """Return if phone is in CSFB call.
1383
1384    Args:
1385        ad: Android device object.
1386    """
1387    return is_phone_in_call_csfb_for_subscription(
1388        log, ad, get_outgoing_voice_sub_id(ad))
1389
1390
1391def is_phone_in_call_csfb_for_subscription(log, ad, sub_id):
1392    """Return if phone is in CSFB call for subscription id.
1393
1394    Args:
1395        ad: Android device object.
1396        sub_id: subscription id.
1397    """
1398    if not ad.droid.telecomIsInCall():
1399        ad.log.error("Not in call.")
1400        return False
1401    nw_type = get_network_rat_for_subscription(log, ad, sub_id,
1402                                               NETWORK_SERVICE_VOICE)
1403    if nw_type == RAT_LTE:
1404        ad.log.error("Voice rat on: %s. Expected: not LTE", nw_type)
1405        return False
1406    return True
1407
1408
1409def is_phone_in_call_3g(log, ad):
1410    """Return if phone is in 3G call.
1411
1412    Args:
1413        ad: Android device object.
1414    """
1415    return is_phone_in_call_3g_for_subscription(log, ad,
1416                                                get_outgoing_voice_sub_id(ad))
1417
1418
1419def is_phone_in_call_3g_for_subscription(log, ad, sub_id):
1420    """Return if phone is in 3G call for subscription id.
1421
1422    Args:
1423        ad: Android device object.
1424        sub_id: subscription id.
1425    """
1426    if not ad.droid.telecomIsInCall():
1427        ad.log.error("Not in call.")
1428        return False
1429    nw_gen = get_network_gen_for_subscription(log, ad, sub_id,
1430                                              NETWORK_SERVICE_VOICE)
1431    if nw_gen != GEN_3G:
1432        ad.log.error("Voice rat on: %s. Expected: 3g", nw_gen)
1433        return False
1434    return True
1435
1436
1437def is_phone_in_call_2g(log, ad):
1438    """Return if phone is in 2G call.
1439
1440    Args:
1441        ad: Android device object.
1442    """
1443    return is_phone_in_call_2g_for_subscription(log, ad,
1444                                                get_outgoing_voice_sub_id(ad))
1445
1446
1447def is_phone_in_call_2g_for_subscription(log, ad, sub_id):
1448    """Return if phone is in 2G call for subscription id.
1449
1450    Args:
1451        ad: Android device object.
1452        sub_id: subscription id.
1453    """
1454    if not ad.droid.telecomIsInCall():
1455        ad.log.error("Not in call.")
1456        return False
1457    nw_gen = get_network_gen_for_subscription(log, ad, sub_id,
1458                                              NETWORK_SERVICE_VOICE)
1459    if nw_gen != GEN_2G:
1460        ad.log.error("Voice rat on: %s. Expected: 2g", nw_gen)
1461        return False
1462    return True
1463
1464
1465def is_phone_in_call_1x(log, ad):
1466    """Return if phone is in 1x call.
1467
1468    Args:
1469        ad: Android device object.
1470    """
1471    return is_phone_in_call_1x_for_subscription(log, ad,
1472                                                get_outgoing_voice_sub_id(ad))
1473
1474
1475def is_phone_in_call_1x_for_subscription(log, ad, sub_id):
1476    """Return if phone is in 1x call for subscription id.
1477
1478    Args:
1479        ad: Android device object.
1480        sub_id: subscription id.
1481    """
1482    if not ad.droid.telecomIsInCall():
1483        ad.log.error("Not in call.")
1484        return False
1485    nw_type = get_network_rat_for_subscription(log, ad, sub_id,
1486                                               NETWORK_SERVICE_VOICE)
1487    if nw_type != RAT_1XRTT:
1488        ad.log.error("Voice rat on: %s. Expected: 1xrtt", nw_type)
1489        return False
1490    return True
1491
1492
1493def is_phone_in_call_wcdma(log, ad):
1494    """Return if phone is in WCDMA call.
1495
1496    Args:
1497        ad: Android device object.
1498    """
1499    return is_phone_in_call_wcdma_for_subscription(
1500        log, ad, get_outgoing_voice_sub_id(ad))
1501
1502
1503def is_phone_in_call_wcdma_for_subscription(log, ad, sub_id):
1504    """Return if phone is in WCDMA call for subscription id.
1505
1506    Args:
1507        ad: Android device object.
1508        sub_id: subscription id.
1509    """
1510    # Currently checking 'umts'.
1511    # Changes may needed in the future.
1512    if not ad.droid.telecomIsInCall():
1513        ad.log.error("Not in call.")
1514        return False
1515    nw_type = get_network_rat_for_subscription(log, ad, sub_id,
1516                                               NETWORK_SERVICE_VOICE)
1517    if nw_type != RAT_UMTS:
1518        ad.log.error("%s voice rat on: %s. Expected: umts", nw_type)
1519        return False
1520    return True
1521
1522
1523def is_phone_in_call_iwlan(log, ad, call_id=None):
1524    """Return if phone is in WiFi call.
1525
1526    Args:
1527        ad: Android device object.
1528    """
1529    if not ad.droid.telecomIsInCall():
1530        ad.log.error("Not in call.")
1531        return False
1532    if not ad.droid.telephonyIsImsRegistered():
1533        ad.log.info("IMS is not registered.")
1534        return False
1535    if not ad.droid.telephonyIsWifiCallingAvailable():
1536        ad.log.info("IsWifiCallingAvailable is False")
1537        return False
1538    if not call_id:
1539        call_ids = ad.droid.telecomCallGetCallIds()
1540        if call_ids:
1541            call_id = call_ids[-1]
1542    if not call_id:
1543        ad.log.error("Failed to get call id")
1544        return False
1545    else:
1546        call_prop = ad.droid.telecomCallGetProperties(call_id)
1547        if "WIFI" not in call_prop:
1548            ad.log.info("callProperties = %s, expecting WIFI", call_prop)
1549            return False
1550    nw_type = get_network_rat(log, ad, NETWORK_SERVICE_DATA)
1551    if nw_type != RAT_IWLAN:
1552        ad.log.warning("Data rat on: %s. Expected: iwlan", nw_type)
1553    return True
1554
1555
1556def is_phone_in_call_not_iwlan(log, ad):
1557    """Return if phone is in WiFi call for subscription id.
1558
1559    Args:
1560        ad: Android device object.
1561        sub_id: subscription id.
1562    """
1563    if not ad.droid.telecomIsInCall():
1564        ad.log.error("Not in call.")
1565        return False
1566    nw_type = get_network_rat(log, ad, NETWORK_SERVICE_DATA)
1567    if nw_type == RAT_IWLAN:
1568        ad.log.error("Data rat on: %s. Expected: not iwlan", nw_type)
1569        return False
1570    if is_wfc_enabled(log, ad):
1571        ad.log.error("WiFi Calling feature bit is True.")
1572        return False
1573    return True
1574
1575
1576def swap_calls(log,
1577               ads,
1578               call_hold_id,
1579               call_active_id,
1580               num_swaps=1,
1581               check_call_status=True):
1582    """PhoneA in call with B and C. Swap active/holding call on PhoneA.
1583
1584    Swap call and check status on PhoneA.
1585        (This step may have multiple times according to 'num_swaps'.)
1586    Check if all 3 phones are 'in-call'.
1587
1588    Args:
1589        ads: list of ad object, at least three need to pass in.
1590            Swap operation will happen on ads[0].
1591            ads[1] and ads[2] are call participants.
1592        call_hold_id: id for the holding call in ads[0].
1593            call_hold_id should be 'STATE_HOLDING' when calling this function.
1594        call_active_id: id for the active call in ads[0].
1595            call_active_id should be 'STATE_ACTIVE' when calling this function.
1596        num_swaps: how many swap/check operations will be done before return.
1597        check_call_status: This is optional. Default value is True.
1598            If this value is True, then call status (active/hold) will be
1599            be checked after each swap operation.
1600
1601    Returns:
1602        If no error happened, return True, otherwise, return False.
1603    """
1604    if check_call_status:
1605        # Check status before swap.
1606        if ads[0].droid.telecomCallGetCallState(
1607                call_active_id) != CALL_STATE_ACTIVE:
1608            ads[0].log.error(
1609                "Call_id:%s, state:%s, expected: STATE_ACTIVE", call_active_id,
1610                ads[0].droid.telecomCallGetCallState(call_active_id))
1611            return False
1612        if ads[0].droid.telecomCallGetCallState(
1613                call_hold_id) != CALL_STATE_HOLDING:
1614            ads[0].log.error(
1615                "Call_id:%s, state:%s, expected: STATE_HOLDING", call_hold_id,
1616                ads[0].droid.telecomCallGetCallState(call_hold_id))
1617            return False
1618
1619    i = 1
1620    while (i <= num_swaps):
1621        ads[0].log.info("swap_test %s: swap and check call status.", i)
1622        ads[0].droid.telecomCallHold(call_active_id)
1623        time.sleep(WAIT_TIME_IN_CALL)
1624        # Swap object reference
1625        call_active_id, call_hold_id = call_hold_id, call_active_id
1626        if check_call_status:
1627            # Check status
1628            if ads[0].droid.telecomCallGetCallState(
1629                    call_active_id) != CALL_STATE_ACTIVE:
1630                ads[0].log.error(
1631                    "Call_id:%s, state:%s, expected: STATE_ACTIVE",
1632                    call_active_id,
1633                    ads[0].droid.telecomCallGetCallState(call_active_id))
1634                return False
1635            if ads[0].droid.telecomCallGetCallState(
1636                    call_hold_id) != CALL_STATE_HOLDING:
1637                ads[0].log.error(
1638                    "Call_id:%s, state:%s, expected: STATE_HOLDING",
1639                    call_hold_id,
1640                    ads[0].droid.telecomCallGetCallState(call_hold_id))
1641                return False
1642        # TODO: b/26296375 add voice check.
1643
1644        i += 1
1645
1646    #In the end, check all three phones are 'in-call'.
1647    if not verify_incall_state(log, [ads[0], ads[1], ads[2]], True):
1648        return False
1649
1650    return True
1651
1652
1653def get_audio_route(log, ad):
1654    """Gets the audio route for the active call
1655
1656    Args:
1657        log: logger object
1658        ad: android_device object
1659
1660    Returns:
1661        Audio route string ["BLUETOOTH", "EARPIECE", "SPEAKER", "WIRED_HEADSET"
1662            "WIRED_OR_EARPIECE"]
1663    """
1664
1665    audio_state = ad.droid.telecomCallGetAudioState()
1666    return audio_state["AudioRoute"]
1667
1668
1669def set_audio_route(log, ad, route):
1670    """Sets the audio route for the active call
1671
1672    Args:
1673        log: logger object
1674        ad: android_device object
1675        route: string ["BLUETOOTH", "EARPIECE", "SPEAKER", "WIRED_HEADSET"
1676            "WIRED_OR_EARPIECE"]
1677
1678    Returns:
1679        If no error happened, return True, otherwise, return False.
1680    """
1681    ad.droid.telecomCallSetAudioRoute(route)
1682    return True
1683
1684
1685def is_property_in_call_properties(log, ad, call_id, expected_property):
1686    """Return if the call_id has the expected property
1687
1688    Args:
1689        log: logger object
1690        ad: android_device object
1691        call_id: call id.
1692        expected_property: expected property.
1693
1694    Returns:
1695        True if call_id has expected_property. False if not.
1696    """
1697    properties = ad.droid.telecomCallGetProperties(call_id)
1698    return (expected_property in properties)
1699
1700
1701def is_call_hd(log, ad, call_id):
1702    """Return if the call_id is HD call.
1703
1704    Args:
1705        log: logger object
1706        ad: android_device object
1707        call_id: call id.
1708
1709    Returns:
1710        True if call_id is HD call. False if not.
1711    """
1712    return is_property_in_call_properties(log, ad, call_id,
1713                                          CALL_PROPERTY_HIGH_DEF_AUDIO)
1714
1715
1716def get_cep_conference_call_id(ad):
1717    """Get CEP conference call id if there is an ongoing CEP conference call.
1718
1719    Args:
1720        ad: android device object.
1721
1722    Returns:
1723        call id for CEP conference call if there is an ongoing CEP conference call.
1724        None otherwise.
1725    """
1726    for call in ad.droid.telecomCallGetCallIds():
1727        if len(ad.droid.telecomCallGetCallChildren(call)) != 0:
1728            return call
1729    return None
1730
1731
1732def is_phone_in_call_on_rat(log, ad, rat='volte', only_return_fn=None):
1733    if rat.lower() == 'volte' or rat.lower() == '5g_volte':
1734        if only_return_fn:
1735            return is_phone_in_call_volte
1736        else:
1737            return is_phone_in_call_volte(log, ad)
1738
1739    elif rat.lower() == 'csfb' or rat.lower() == '5g_csfb':
1740        if only_return_fn:
1741            return is_phone_in_call_csfb
1742        else:
1743            return is_phone_in_call_csfb(log, ad)
1744
1745    elif rat.lower() == '3g':
1746        if only_return_fn:
1747            return is_phone_in_call_3g
1748        else:
1749            return is_phone_in_call_3g(log, ad)
1750
1751    elif rat.lower() == '2g':
1752        if only_return_fn:
1753            return is_phone_in_call_2g
1754        else:
1755            return is_phone_in_call_2g(log, ad)
1756
1757    elif rat.lower() == 'wfc' or rat.lower() == '5g_wfc':
1758        if only_return_fn:
1759            return is_phone_in_call_iwlan
1760        else:
1761            return is_phone_in_call_iwlan(log, ad)
1762    else:
1763        return None
1764
1765
1766def hold_unhold_test(log, ads):
1767    """ Test hold/unhold functionality.
1768
1769    PhoneA is in call with PhoneB. The call on PhoneA is active.
1770    Get call list on PhoneA.
1771    Hold call_id on PhoneA.
1772    Check call_id state.
1773    Unhold call_id on PhoneA.
1774    Check call_id state.
1775
1776    Args:
1777        log: log object
1778        ads: List of android objects.
1779            This list should contain 2 android objects.
1780            ads[0] is the ad to do hold/unhold operation.
1781
1782    Returns:
1783        List of test result and call states.
1784        The first element of the list is always the test result.
1785        True if pass; False if fail.
1786        The rest of the list contains call states.
1787    """
1788    call_list = ads[0].droid.telecomCallGetCallIds()
1789    log.info("Calls in PhoneA %s", call_list)
1790    if num_active_calls(ads[0].log, ads[0]) != 1:
1791        log.error("No voice call or too many voice calls in PhoneA!")
1792        call_state_list = [ads[0].droid.telecomCallGetCallState(call_id) for call_id in call_list]
1793        return [False] + call_state_list
1794    call_id = call_list[0]
1795
1796    call_state = ads[0].droid.telecomCallGetCallState(call_id)
1797    if call_state != CALL_STATE_ACTIVE:
1798        log.error("Call_id:%s, state:%s, expected: STATE_ACTIVE",
1799                  call_id,
1800                  ads[0].droid.telecomCallGetCallState(call_id))
1801        return [False, call_state]
1802    # TODO: b/26296375 add voice check.
1803
1804    log.info("Hold call_id %s on PhoneA", call_id)
1805    ads[0].droid.telecomCallHold(call_id)
1806    time.sleep(WAIT_TIME_IN_CALL)
1807
1808    call_state = ads[0].droid.telecomCallGetCallState(call_id)
1809    if call_state != CALL_STATE_HOLDING:
1810        ads[0].log.error("Call_id:%s, state:%s, expected: STATE_HOLDING",
1811                         call_id,
1812                         ads[0].droid.telecomCallGetCallState(call_id))
1813        return [False, call_state]
1814    # TODO: b/26296375 add voice check.
1815
1816    log.info("Unhold call_id %s on PhoneA", call_id)
1817    ads[0].droid.telecomCallUnhold(call_id)
1818    time.sleep(WAIT_TIME_IN_CALL)
1819
1820    call_state = ads[0].droid.telecomCallGetCallState(call_id)
1821    if call_state != CALL_STATE_ACTIVE:
1822        log.error("Call_id:%s, state:%s, expected: STATE_ACTIVE",
1823                  call_id,
1824                  call_state)
1825        return [False, call_state]
1826    # TODO: b/26296375 add voice check.
1827
1828    return [True, call_state]
1829
1830
1831def phone_setup_call_hold_unhold_test(log,
1832                                      ads,
1833                                      call_direction=DIRECTION_MOBILE_ORIGINATED,
1834                                      caller_func=None,
1835                                      callee_func=None):
1836    """Test hold and unhold in voice call.
1837
1838    1. Clear call list.
1839    2. Set up MO/MT call.
1840    3. Test hold and unhold in call.
1841    4. hangup call.
1842
1843    Args:
1844        log: log object
1845        ads: list of android objects, this list should have two ad.
1846        call_direction: MO(DIRECTION_MOBILE_ORIGINATED) or MT(DIRECTION_MOBILE_TERMINATED) call.
1847        caller_func: function to verify caller is in correct state while in-call.
1848        callee_func: function to verify callee is in correct state while in-call.
1849
1850    Returns:
1851        True if pass; False if fail.
1852    """
1853
1854    ads[0].droid.telecomCallClearCallList()
1855    if num_active_calls(log, ads[0]) != 0:
1856        ads[0].log.error("call list is not empty")
1857        return False
1858    log.info("begin hold/unhold test")
1859
1860    ad_caller = ads[0]
1861    ad_callee = ads[1]
1862
1863    if call_direction != DIRECTION_MOBILE_ORIGINATED:
1864        ad_caller = ads[1]
1865        ad_callee = ads[0]
1866
1867    if not call_setup_teardown(
1868                log,
1869                ad_caller,
1870                ad_callee,
1871                ad_hangup=None,
1872                verify_caller_func=caller_func,
1873                verify_callee_func=callee_func):
1874        return False
1875
1876    if not hold_unhold_test(ads[0].log, ads)[0]:
1877        log.error("hold/unhold test fail.")
1878        # hangup call in case voice call is still active.
1879        hangup_call(log, ads[0])
1880        return False
1881
1882    if not hangup_call(log, ads[0]):
1883        log.error("call hangup failed")
1884        return False
1885    return True
1886
1887
1888def _test_call_long_duration(log, ads, dut_incall_check_func, total_duration):
1889
1890    log.info("Long Duration Call Test. Total duration = %s",
1891                  total_duration)
1892    return call_setup_teardown(
1893        log,
1894        ads[0],
1895        ads[1],
1896        ads[0],
1897        verify_caller_func=dut_incall_check_func,
1898        wait_time_in_call=total_duration)
1899
1900
1901def _wait_for_ringing_event(log, ad, wait_time):
1902    """Wait for ringing event.
1903
1904    Args:
1905        log: log object.
1906        ad: android device object.
1907        wait_time: max time to wait for ringing event.
1908
1909    Returns:
1910        event_ringing if received ringing event.
1911        otherwise return None.
1912    """
1913    event_ringing = None
1914
1915    try:
1916        event_ringing = ad.ed.wait_for_event(
1917            EventCallStateChanged,
1918            is_event_match,
1919            timeout=wait_time,
1920            field=CallStateContainer.CALL_STATE,
1921            value=TELEPHONY_STATE_RINGING)
1922        ad.log.info("Receive ringing event")
1923    except Empty:
1924        ad.log.info("No Ringing Event")
1925    finally:
1926        return event_ringing
1927
1928
1929def wait_for_telecom_ringing(log, ad, max_time=MAX_WAIT_TIME_TELECOM_RINGING):
1930    """Wait for android to be in telecom ringing state.
1931
1932    Args:
1933        log: log object.
1934        ad:  android device.
1935        max_time: maximal wait time. This is optional.
1936            Default Value is MAX_WAIT_TIME_TELECOM_RINGING.
1937
1938    Returns:
1939        If phone become in telecom ringing state within max_time, return True.
1940        Return False if timeout.
1941    """
1942    return _wait_for_droid_in_state(
1943        log, ad, max_time, lambda log, ad: ad.droid.telecomIsRinging())
1944
1945
1946def wait_for_ringing_call(log, ad, incoming_number=None):
1947    """Wait for an incoming call on default voice subscription and
1948       accepts the call.
1949
1950    Args:
1951        log: log object.
1952        ad: android device object.
1953        incoming_number: Expected incoming number.
1954            Optional. Default is None
1955
1956    Returns:
1957        True: if incoming call is received and answered successfully.
1958        False: for errors
1959        """
1960    return wait_for_ringing_call_for_subscription(
1961        log, ad, get_incoming_voice_sub_id(ad), incoming_number)
1962
1963
1964def wait_for_ringing_call_for_subscription(
1965        log,
1966        ad,
1967        sub_id,
1968        incoming_number=None,
1969        caller=None,
1970        event_tracking_started=False,
1971        timeout=MAX_WAIT_TIME_CALLEE_RINGING,
1972        interval=WAIT_TIME_BETWEEN_STATE_CHECK):
1973    """Wait for an incoming call on specified subscription.
1974
1975    Args:
1976        log: log object.
1977        ad: android device object.
1978        sub_id: subscription ID
1979        incoming_number: Expected incoming number. Default is None
1980        event_tracking_started: True if event tracking already state outside
1981        timeout: time to wait for ring
1982        interval: checking interval
1983
1984    Returns:
1985        True: if incoming call is received and answered successfully.
1986        False: for errors
1987    """
1988    if not event_tracking_started:
1989        ad.ed.clear_events(EventCallStateChanged)
1990        ad.droid.telephonyStartTrackingCallStateForSubscription(sub_id)
1991    ring_event_received = False
1992    end_time = time.time() + timeout
1993    try:
1994        while time.time() < end_time:
1995            if not ring_event_received:
1996                event_ringing = _wait_for_ringing_event(log, ad, interval)
1997                if event_ringing:
1998                    if incoming_number and not check_phone_number_match(
1999                            event_ringing['data']
2000                        [CallStateContainer.INCOMING_NUMBER], incoming_number):
2001                        ad.log.error(
2002                            "Incoming Number not match. Expected number:%s, actual number:%s",
2003                            incoming_number, event_ringing['data'][
2004                                CallStateContainer.INCOMING_NUMBER])
2005                        return False
2006                    ring_event_received = True
2007            telephony_state = ad.droid.telephonyGetCallStateForSubscription(
2008                sub_id)
2009            telecom_state = ad.droid.telecomGetCallState()
2010            if telephony_state == TELEPHONY_STATE_RINGING and (
2011                    telecom_state == TELEPHONY_STATE_RINGING):
2012                ad.log.info("callee is in telephony and telecom RINGING state")
2013                if caller:
2014                    if caller.droid.telecomIsInCall():
2015                        caller.log.info("Caller telecom is in call state")
2016                        return True
2017                    else:
2018                        caller.log.info("Caller telecom is NOT in call state")
2019                else:
2020                    return True
2021            else:
2022                ad.log.info(
2023                    "telephony in %s, telecom in %s, expecting RINGING state",
2024                    telephony_state, telecom_state)
2025            time.sleep(interval)
2026    finally:
2027        if not event_tracking_started:
2028            ad.droid.telephonyStopTrackingCallStateChangeForSubscription(
2029                sub_id)
2030
2031
2032def wait_for_call_offhook_for_subscription(
2033        log,
2034        ad,
2035        sub_id,
2036        event_tracking_started=False,
2037        timeout=MAX_WAIT_TIME_ACCEPT_CALL_TO_OFFHOOK_EVENT,
2038        interval=WAIT_TIME_BETWEEN_STATE_CHECK):
2039    """Wait for an incoming call on specified subscription.
2040
2041    Args:
2042        log: log object.
2043        ad: android device object.
2044        sub_id: subscription ID
2045        timeout: time to wait for ring
2046        interval: checking interval
2047
2048    Returns:
2049        True: if incoming call is received and answered successfully.
2050        False: for errors
2051    """
2052    if not event_tracking_started:
2053        ad.ed.clear_events(EventCallStateChanged)
2054        ad.droid.telephonyStartTrackingCallStateForSubscription(sub_id)
2055    offhook_event_received = False
2056    end_time = time.time() + timeout
2057    try:
2058        while time.time() < end_time:
2059            if not offhook_event_received:
2060                if wait_for_call_offhook_event(log, ad, sub_id, True,
2061                                               interval):
2062                    offhook_event_received = True
2063            telephony_state = ad.droid.telephonyGetCallStateForSubscription(
2064                sub_id)
2065            telecom_state = ad.droid.telecomGetCallState()
2066            if telephony_state == TELEPHONY_STATE_OFFHOOK and (
2067                    telecom_state == TELEPHONY_STATE_OFFHOOK):
2068                ad.log.info("telephony and telecom are in OFFHOOK state")
2069                return True
2070            else:
2071                ad.log.info(
2072                    "telephony in %s, telecom in %s, expecting OFFHOOK state",
2073                    telephony_state, telecom_state)
2074            if offhook_event_received:
2075                time.sleep(interval)
2076    finally:
2077        if not event_tracking_started:
2078            ad.droid.telephonyStopTrackingCallStateChangeForSubscription(
2079                sub_id)
2080
2081
2082def wait_for_call_offhook_event(
2083        log,
2084        ad,
2085        sub_id,
2086        event_tracking_started=False,
2087        timeout=MAX_WAIT_TIME_ACCEPT_CALL_TO_OFFHOOK_EVENT):
2088    """Wait for an incoming call on specified subscription.
2089
2090    Args:
2091        log: log object.
2092        ad: android device object.
2093        event_tracking_started: True if event tracking already state outside
2094        timeout: time to wait for event
2095
2096    Returns:
2097        True: if call offhook event is received.
2098        False: if call offhook event is not received.
2099    """
2100    if not event_tracking_started:
2101        ad.ed.clear_events(EventCallStateChanged)
2102        ad.droid.telephonyStartTrackingCallStateForSubscription(sub_id)
2103    try:
2104        ad.ed.wait_for_event(
2105            EventCallStateChanged,
2106            is_event_match,
2107            timeout=timeout,
2108            field=CallStateContainer.CALL_STATE,
2109            value=TELEPHONY_STATE_OFFHOOK)
2110        ad.log.info("Got event %s", TELEPHONY_STATE_OFFHOOK)
2111    except Empty:
2112        ad.log.info("No event for call state change to OFFHOOK")
2113        return False
2114    finally:
2115        if not event_tracking_started:
2116            ad.droid.telephonyStopTrackingCallStateChangeForSubscription(
2117                sub_id)
2118    return True
2119
2120
2121def wait_and_answer_call_for_subscription(
2122        log,
2123        ad,
2124        sub_id,
2125        incoming_number=None,
2126        incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND,
2127        timeout=MAX_WAIT_TIME_CALLEE_RINGING,
2128        caller=None,
2129        video_state=None):
2130    """Wait for an incoming call on specified subscription and
2131       accepts the call.
2132
2133    Args:
2134        log: log object.
2135        ad: android device object.
2136        sub_id: subscription ID
2137        incoming_number: Expected incoming number.
2138            Optional. Default is None
2139        incall_ui_display: after answer the call, bring in-call UI to foreground or
2140            background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND.
2141            if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground.
2142            if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background.
2143            else, do nothing.
2144
2145    Returns:
2146        True: if incoming call is received and answered successfully.
2147        False: for errors
2148    """
2149    ad.ed.clear_events(EventCallStateChanged)
2150    ad.droid.telephonyStartTrackingCallStateForSubscription(sub_id)
2151    try:
2152        if not wait_for_ringing_call_for_subscription(
2153                log,
2154                ad,
2155                sub_id,
2156                incoming_number=incoming_number,
2157                caller=caller,
2158                event_tracking_started=True,
2159                timeout=timeout):
2160            ad.log.info("Incoming call ringing check failed.")
2161            return False
2162        ad.log.info("Accept the ring call")
2163        ad.droid.telecomAcceptRingingCall(video_state)
2164
2165        if wait_for_call_offhook_for_subscription(
2166                log, ad, sub_id, event_tracking_started=True):
2167            return True
2168        else:
2169            ad.log.error("Could not answer the call.")
2170            return False
2171    except Exception as e:
2172        log.error(e)
2173        return False
2174    finally:
2175        ad.droid.telephonyStopTrackingCallStateChangeForSubscription(sub_id)
2176        if incall_ui_display == INCALL_UI_DISPLAY_FOREGROUND:
2177            ad.droid.telecomShowInCallScreen()
2178        elif incall_ui_display == INCALL_UI_DISPLAY_BACKGROUND:
2179            ad.droid.showHomeScreen()
2180
2181
2182def wait_and_reject_call(log,
2183                         ad,
2184                         incoming_number=None,
2185                         delay_reject=WAIT_TIME_REJECT_CALL,
2186                         reject=True):
2187    """Wait for an incoming call on default voice subscription and
2188       reject the call.
2189
2190    Args:
2191        log: log object.
2192        ad: android device object.
2193        incoming_number: Expected incoming number.
2194            Optional. Default is None
2195        delay_reject: time to wait before rejecting the call
2196            Optional. Default is WAIT_TIME_REJECT_CALL
2197
2198    Returns:
2199        True: if incoming call is received and reject successfully.
2200        False: for errors
2201    """
2202    return wait_and_reject_call_for_subscription(log, ad,
2203                                                 get_incoming_voice_sub_id(ad),
2204                                                 incoming_number, delay_reject,
2205                                                 reject)
2206
2207
2208def wait_and_reject_call_for_subscription(log,
2209                                          ad,
2210                                          sub_id,
2211                                          incoming_number=None,
2212                                          delay_reject=WAIT_TIME_REJECT_CALL,
2213                                          reject=True):
2214    """Wait for an incoming call on specific subscription and
2215       reject the call.
2216
2217    Args:
2218        log: log object.
2219        ad: android device object.
2220        sub_id: subscription ID
2221        incoming_number: Expected incoming number.
2222            Optional. Default is None
2223        delay_reject: time to wait before rejecting the call
2224            Optional. Default is WAIT_TIME_REJECT_CALL
2225
2226    Returns:
2227        True: if incoming call is received and reject successfully.
2228        False: for errors
2229    """
2230
2231    if not wait_for_ringing_call_for_subscription(log, ad, sub_id,
2232                                                  incoming_number):
2233        ad.log.error(
2234            "Could not reject a call: incoming call in ringing check failed.")
2235        return False
2236
2237    ad.ed.clear_events(EventCallStateChanged)
2238    ad.droid.telephonyStartTrackingCallStateForSubscription(sub_id)
2239    if reject is True:
2240        # Delay between ringing and reject.
2241        time.sleep(delay_reject)
2242        is_find = False
2243        # Loop the call list and find the matched one to disconnect.
2244        for call in ad.droid.telecomCallGetCallIds():
2245            if check_phone_number_match(
2246                    get_number_from_tel_uri(get_call_uri(ad, call)),
2247                    incoming_number):
2248                ad.droid.telecomCallDisconnect(call)
2249                ad.log.info("Callee reject the call")
2250                is_find = True
2251        if is_find is False:
2252            ad.log.error("Callee did not find matching call to reject.")
2253            return False
2254    else:
2255        # don't reject on callee. Just ignore the incoming call.
2256        ad.log.info("Callee received incoming call. Ignore it.")
2257    try:
2258        ad.ed.wait_for_event(
2259            EventCallStateChanged,
2260            is_event_match_for_list,
2261            timeout=MAX_WAIT_TIME_CALL_IDLE_EVENT,
2262            field=CallStateContainer.CALL_STATE,
2263            value_list=[TELEPHONY_STATE_IDLE, TELEPHONY_STATE_OFFHOOK])
2264    except Empty:
2265        ad.log.error("No onCallStateChangedIdle event received.")
2266        return False
2267    finally:
2268        ad.droid.telephonyStopTrackingCallStateChangeForSubscription(sub_id)
2269    return True
2270
2271
2272def wait_and_answer_call(log,
2273                         ad,
2274                         incoming_number=None,
2275                         incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND,
2276                         caller=None,
2277                         video_state=None):
2278    """Wait for an incoming call on default voice subscription and
2279       accepts the call.
2280
2281    Args:
2282        ad: android device object.
2283        incoming_number: Expected incoming number.
2284            Optional. Default is None
2285        incall_ui_display: after answer the call, bring in-call UI to foreground or
2286            background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND.
2287            if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground.
2288            if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background.
2289            else, do nothing.
2290
2291    Returns:
2292        True: if incoming call is received and answered successfully.
2293        False: for errors
2294        """
2295    return wait_and_answer_call_for_subscription(
2296        log,
2297        ad,
2298        get_incoming_voice_sub_id(ad),
2299        incoming_number,
2300        incall_ui_display=incall_ui_display,
2301        caller=caller,
2302        video_state=video_state)
2303
2304
2305def wait_for_in_call_active(ad,
2306                            timeout=MAX_WAIT_TIME_ACCEPT_CALL_TO_OFFHOOK_EVENT,
2307                            interval=WAIT_TIME_BETWEEN_STATE_CHECK,
2308                            call_id=None):
2309    """Wait for call reach active state.
2310
2311    Args:
2312        log: log object.
2313        ad:  android device.
2314        call_id: the call id
2315    """
2316    if not call_id:
2317        call_id = ad.droid.telecomCallGetCallIds()[0]
2318    args = [ad, call_id]
2319    if not wait_for_state(is_phone_in_call_active, True, timeout, interval,
2320                          *args):
2321        ad.log.error("Call did not reach ACTIVE state")
2322        return False
2323    else:
2324        return True
2325
2326
2327def wait_for_droid_in_call(log, ad, max_time):
2328    """Wait for android to be in call state.
2329
2330    Args:
2331        log: log object.
2332        ad:  android device.
2333        max_time: maximal wait time.
2334
2335    Returns:
2336        If phone become in call state within max_time, return True.
2337        Return False if timeout.
2338    """
2339    return _wait_for_droid_in_state(log, ad, max_time, is_phone_in_call)
2340
2341
2342def wait_for_call_id_clearing(ad,
2343                              previous_ids,
2344                              timeout=MAX_WAIT_TIME_CALL_DROP):
2345    while timeout > 0:
2346        new_call_ids = ad.droid.telecomCallGetCallIds()
2347        if len(new_call_ids) <= len(previous_ids):
2348            return True
2349        time.sleep(5)
2350        timeout = timeout - 5
2351    ad.log.error("Call id clearing failed. Before: %s; After: %s",
2352                 previous_ids, new_call_ids)
2353    return False
2354
2355
2356def wait_for_call_end(
2357        log,
2358        ad_caller,
2359        ad_callee,
2360        ad_hangup,
2361        verify_caller_func,
2362        verify_callee_func,
2363        call_begin_time,
2364        check_interval=5,
2365        tel_result_wrapper=TelResultWrapper(CallResult('SUCCESS')),
2366        wait_time_in_call=WAIT_TIME_IN_CALL):
2367    elapsed_time = 0
2368    while (elapsed_time < wait_time_in_call):
2369        check_interval = min(check_interval, wait_time_in_call - elapsed_time)
2370        time.sleep(check_interval)
2371        elapsed_time += check_interval
2372        time_message = "at <%s>/<%s> second." % (elapsed_time, wait_time_in_call)
2373        for ad, call_func in [(ad_caller, verify_caller_func),
2374                              (ad_callee, verify_callee_func)]:
2375            if not call_func(log, ad):
2376                ad.log.error(
2377                    "NOT in correct %s state at %s, voice in RAT %s",
2378                    call_func.__name__,
2379                    time_message,
2380                    ad.droid.telephonyGetCurrentVoiceNetworkType())
2381                tel_result_wrapper.result_value = CallResult(
2382                    'CALL_DROP_OR_WRONG_STATE_AFTER_CONNECTED')
2383            else:
2384                ad.log.info("In correct %s state at %s",
2385                    call_func.__name__, time_message)
2386            if not ad.droid.telecomCallGetAudioState():
2387                ad.log.error("Audio is not in call state at %s", time_message)
2388                tel_result_wrapper.result_value = CallResult(
2389                        'AUDIO_STATE_NOT_INCALL_AFTER_CONNECTED')
2390
2391        if not tel_result_wrapper:
2392            break
2393
2394    if not tel_result_wrapper:
2395        for ad in (ad_caller, ad_callee):
2396            last_call_drop_reason(ad, call_begin_time)
2397            try:
2398                if ad.droid.telecomIsInCall():
2399                    ad.log.info("In call. End now.")
2400                    ad.droid.telecomEndCall()
2401            except Exception as e:
2402                log.error(str(e))
2403    else:
2404        if ad_hangup:
2405            if not hangup_call(log, ad_hangup):
2406                ad_hangup.log.info("Failed to hang up the call")
2407                tel_result_wrapper.result_value = CallResult('CALL_HANGUP_FAIL')
2408
2409    if ad_hangup or not tel_result_wrapper:
2410        for ad in (ad_caller, ad_callee):
2411            if not wait_for_call_id_clearing(ad, getattr(ad, "caller_ids", [])):
2412                tel_result_wrapper.result_value = CallResult(
2413                    'CALL_ID_CLEANUP_FAIL')
2414
2415    return tel_result_wrapper
2416
2417
2418def check_call(log, dut, dut_client):
2419    result = True
2420    if not call_setup_teardown(log, dut_client, dut,
2421                               dut):
2422        if not call_setup_teardown(log, dut_client,
2423                                   dut, dut):
2424            dut.log.error("MT call failed")
2425            result = False
2426    if not call_setup_teardown(log, dut, dut_client,
2427                               dut):
2428        dut.log.error("MO call failed")
2429        result = False
2430    return result
2431
2432
2433def check_call_in_wfc(log, dut, dut_client):
2434    result = True
2435    if not call_setup_teardown(log, dut_client, dut,
2436                               dut, None, is_phone_in_call_iwlan):
2437        if not call_setup_teardown(log, dut_client,
2438                                   dut, dut, None,
2439                                   is_phone_in_call_iwlan):
2440            dut.log.error("MT WFC call failed")
2441            result = False
2442    if not call_setup_teardown(log, dut, dut_client,
2443                               dut, is_phone_in_call_iwlan):
2444        dut.log.error("MO WFC call failed")
2445        result = False
2446    return result
2447
2448
2449def check_call_in_volte(log, dut, dut_client):
2450    result = True
2451    if not call_setup_teardown(log, dut_client, dut,
2452                               dut, None, is_phone_in_call_volte):
2453        if not call_setup_teardown(log, dut_client,
2454                                   dut, dut, None,
2455                                   is_phone_in_call_volte):
2456            dut.log.error("MT VoLTE call failed")
2457            result = False
2458    if not call_setup_teardown(log, dut, dut_client,
2459                               dut, is_phone_in_call_volte):
2460        dut.log.error("MO VoLTE call failed")
2461        result = False
2462    return result
2463
2464
2465def change_ims_setting(log,
2466                       ad,
2467                       dut_client,
2468                       wifi_network_ssid,
2469                       wifi_network_pass,
2470                       subid,
2471                       dut_capabilities,
2472                       airplane_mode,
2473                       wifi_enabled,
2474                       volte_enabled,
2475                       wfc_enabled,
2476                       nw_gen=RAT_LTE,
2477                       wfc_mode=None):
2478    result = True
2479    ad.log.info(
2480        "Setting APM %s, WIFI %s, VoLTE %s, WFC %s, WFC mode %s",
2481        airplane_mode, wifi_enabled, volte_enabled, wfc_enabled, wfc_mode)
2482
2483    toggle_airplane_mode_by_adb(log, ad, airplane_mode)
2484    if wifi_enabled:
2485        if not ensure_wifi_connected(log, ad,
2486                                     wifi_network_ssid,
2487                                     wifi_network_pass,
2488                                     apm=airplane_mode):
2489            ad.log.error("Fail to connected to WiFi")
2490            result = False
2491    else:
2492        if not wifi_toggle_state(log, ad, False):
2493            ad.log.error("Failed to turn off WiFi.")
2494            result = False
2495    toggle_volte(log, ad, volte_enabled)
2496    toggle_wfc(log, ad, wfc_enabled)
2497    if wfc_mode:
2498        set_wfc_mode(log, ad, wfc_mode)
2499    wfc_mode = ad.droid.imsGetWfcMode()
2500    if wifi_enabled or not airplane_mode:
2501        if not ensure_phone_subscription(log, ad):
2502            ad.log.error("Failed to find valid subscription")
2503            result = False
2504    if airplane_mode:
2505        if (CAPABILITY_WFC in dut_capabilities) and (wifi_enabled
2506                                                          and wfc_enabled):
2507            if not wait_for_wfc_enabled(log, ad):
2508                result = False
2509            elif not check_call_in_wfc(log, ad, dut_client):
2510                result = False
2511        else:
2512            if not wait_for_state(
2513                    ad.droid.telephonyGetCurrentVoiceNetworkType,
2514                    RAT_UNKNOWN):
2515                ad.log.error(
2516                    "Voice RAT is %s not UNKNOWN",
2517                    ad.droid.telephonyGetCurrentVoiceNetworkType())
2518                result = False
2519            else:
2520                ad.log.info("Voice RAT is in UNKKNOWN")
2521    else:
2522        if (wifi_enabled and wfc_enabled) and (
2523                wfc_mode == WFC_MODE_WIFI_PREFERRED) and (
2524                    CAPABILITY_WFC in dut_capabilities):
2525            if not wait_for_wfc_enabled(log, ad):
2526                result = False
2527            if not wait_for_state(
2528                    ad.droid.telephonyGetCurrentVoiceNetworkType,
2529                    RAT_UNKNOWN):
2530                ad.log.error(
2531                    "Voice RAT is %s, not UNKNOWN",
2532                    ad.droid.telephonyGetCurrentVoiceNetworkType())
2533            if not check_call_in_wfc(log, ad, dut_client):
2534                result = False
2535        else:
2536            if not wait_for_wfc_disabled(log, ad):
2537               ad.log.error("WFC is not disabled")
2538               result = False
2539            if volte_enabled and CAPABILITY_VOLTE in dut_capabilities:
2540               if not wait_for_volte_enabled(log, ad):
2541                    result = False
2542               if not check_call_in_volte(log, ad, dut_client):
2543                    result = False
2544            else:
2545                if not wait_for_not_network_rat(
2546                        log,
2547                        ad,
2548                        nw_gen,
2549                        voice_or_data=NETWORK_SERVICE_VOICE):
2550                    ad.log.error(
2551                        "Voice RAT is %s",
2552                        ad.droid.telephonyGetCurrentVoiceNetworkType(
2553                        ))
2554                    result = False
2555                if not wait_for_voice_attach(log, ad):
2556                    result = False
2557                if not check_call(log, ad, dut_client):
2558                    result = False
2559    user_config_profile = get_user_config_profile(ad)
2560    ad.log.info("user_config_profile: %s ",
2561                      sorted(user_config_profile.items()))
2562    return result
2563
2564
2565def verify_default_ims_setting(log,
2566                       ad,
2567                       dut_client,
2568                       carrier_configs,
2569                       default_wfc_enabled,
2570                       default_volte,
2571                       wfc_mode=None):
2572    result = True
2573    airplane_mode = ad.droid.connectivityCheckAirplaneMode()
2574    default_wfc_mode = carrier_configs.get(
2575        CarrierConfigs.DEFAULT_WFC_IMS_MODE_INT, wfc_mode)
2576    if default_wfc_enabled:
2577        wait_for_wfc_enabled(log, ad)
2578    else:
2579        wait_for_wfc_disabled(log, ad)
2580        if airplane_mode:
2581            wait_for_network_rat(
2582                log,
2583                ad,
2584                RAT_UNKNOWN,
2585                voice_or_data=NETWORK_SERVICE_VOICE)
2586        else:
2587            if default_volte:
2588                wait_for_volte_enabled(log, ad)
2589            else:
2590                wait_for_not_network_rat(
2591                    log,
2592                    ad,
2593                    RAT_UNKNOWN,
2594                    voice_or_data=NETWORK_SERVICE_VOICE)
2595
2596    if not ensure_phone_subscription(log, ad):
2597        ad.log.error("Failed to find valid subscription")
2598        result = False
2599    user_config_profile = get_user_config_profile(ad)
2600    ad.log.info("user_config_profile = %s ",
2601                      sorted(user_config_profile.items()))
2602    if user_config_profile["VoLTE Enabled"] != default_volte:
2603        ad.log.error("VoLTE mode is not %s", default_volte)
2604        result = False
2605    else:
2606        ad.log.info("VoLTE mode is %s as expected",
2607                          default_volte)
2608    if user_config_profile["WFC Enabled"] != default_wfc_enabled:
2609        ad.log.error("WFC enabled is not %s", default_wfc_enabled)
2610    if user_config_profile["WFC Enabled"]:
2611        if user_config_profile["WFC Mode"] != default_wfc_mode:
2612            ad.log.error(
2613                "WFC mode is not %s after IMS factory reset",
2614                default_wfc_mode)
2615            result = False
2616        else:
2617            ad.log.info("WFC mode is %s as expected",
2618                              default_wfc_mode)
2619    if default_wfc_enabled and \
2620        default_wfc_mode == WFC_MODE_WIFI_PREFERRED:
2621        if not check_call_in_wfc(log, ad, dut_client):
2622            result = False
2623    elif not airplane_mode:
2624        if default_volte:
2625            if not check_call_in_volte(log, ad, dut_client):
2626                result = False
2627        else:
2628            if not check_call(log, ad, dut_client):
2629                result = False
2630    if result == False:
2631        user_config_profile = get_user_config_profile(ad)
2632        ad.log.info("user_config_profile = %s ",
2633                          sorted(user_config_profile.items()))
2634    return result
2635
2636
2637def truncate_phone_number(
2638    log,
2639    caller_number,
2640    callee_number,
2641    dialing_number_length,
2642    skip_inter_area_call=False):
2643    """This function truncates the phone number of the caller/callee to test
2644    7/10/11/12 digit dialing for North American numbering plan, and distinguish
2645    if this is an inter-area call by comparing the area code.
2646
2647    Args:
2648        log: logger object
2649        caller_number: phone number of the caller
2650        callee_number: phone number of the callee
2651        dialing_number_length: the length of phone number (usually 7/10/11/12)
2652        skip_inter_area_call: True to raise a TestSkip exception to skip dialing
2653            the inter-area call. Otherwise False.
2654
2655    Returns:
2656        The truncated phone number of the callee
2657    """
2658
2659    if not dialing_number_length:
2660        return callee_number
2661
2662    trunc_position = 0 - int(dialing_number_length)
2663    try:
2664        caller_area_code = caller_number[:trunc_position]
2665        callee_area_code = callee_number[:trunc_position]
2666        callee_dial_number = callee_number[trunc_position:]
2667
2668        if caller_area_code != callee_area_code:
2669            skip_inter_area_call = True
2670
2671    except:
2672        skip_inter_area_call = True
2673
2674    if skip_inter_area_call:
2675        msg = "Cannot make call from %s to %s by %s digits since inter-area \
2676        call is not allowed" % (
2677            caller_number, callee_number, dialing_number_length)
2678        log.info(msg)
2679        raise signals.TestSkip(msg)
2680    else:
2681        callee_number = callee_dial_number
2682
2683    return callee_number
2684
2685