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