1#!/usr/bin/env python3
2#
3#   Copyright 2016 - Google
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17import time
18from queue import Empty
19from acts_contrib.test_utils.tel.tel_defines import AUDIO_ROUTE_EARPIECE
20from acts_contrib.test_utils.tel.tel_defines import CALL_STATE_RINGING
21from acts_contrib.test_utils.tel.tel_defines import INCALL_UI_DISPLAY_BACKGROUND
22from acts_contrib.test_utils.tel.tel_defines import INCALL_UI_DISPLAY_FOREGROUND
23from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_ACCEPT_CALL_TO_OFFHOOK_EVENT
24from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_CALL_INITIATION
25from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_CALLEE_RINGING
26from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_NW_SELECTION
27from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_TELECOM_RINGING
28from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_VIDEO_SESSION_EVENT
29from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_VOLTE_ENABLED
30from acts_contrib.test_utils.tel.tel_defines import NETWORK_SERVICE_DATA
31from acts_contrib.test_utils.tel.tel_defines import NETWORK_SERVICE_VOICE
32from acts_contrib.test_utils.tel.tel_defines import GEN_4G
33from acts_contrib.test_utils.tel.tel_defines import RAT_1XRTT
34from acts_contrib.test_utils.tel.tel_defines import RAT_IWLAN
35from acts_contrib.test_utils.tel.tel_defines import RAT_LTE
36from acts_contrib.test_utils.tel.tel_defines import RAT_UMTS
37from acts_contrib.test_utils.tel.tel_defines import TELEPHONY_STATE_OFFHOOK
38from acts_contrib.test_utils.tel.tel_defines import TELEPHONY_STATE_RINGING
39from acts_contrib.test_utils.tel.tel_defines import VT_STATE_AUDIO_ONLY
40from acts_contrib.test_utils.tel.tel_defines import VT_STATE_BIDIRECTIONAL
41from acts_contrib.test_utils.tel.tel_defines import VT_STATE_BIDIRECTIONAL_PAUSED
42from acts_contrib.test_utils.tel.tel_defines import VT_STATE_RX_ENABLED
43from acts_contrib.test_utils.tel.tel_defines import VT_STATE_RX_PAUSED
44from acts_contrib.test_utils.tel.tel_defines import VT_STATE_TX_ENABLED
45from acts_contrib.test_utils.tel.tel_defines import VT_STATE_TX_PAUSED
46from acts_contrib.test_utils.tel.tel_defines import VT_STATE_STATE_INVALID
47from acts_contrib.test_utils.tel.tel_defines import VT_VIDEO_QUALITY_DEFAULT
48from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_ACCEPT_VIDEO_CALL_TO_CHECK_STATE
49from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING
50from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_IN_CALL
51from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_DISABLED
52from acts_contrib.test_utils.tel.tel_defines import EventCallStateChanged
53from acts_contrib.test_utils.tel.tel_defines import EventTelecomVideoCallSessionModifyRequestReceived
54from acts_contrib.test_utils.tel.tel_defines import EventTelecomVideoCallSessionModifyResponseReceived
55from acts_contrib.test_utils.tel.tel_defines import EVENT_VIDEO_SESSION_MODIFY_RESPONSE_RECEIVED
56from acts_contrib.test_utils.tel.tel_defines import EVENT_VIDEO_SESSION_MODIFY_REQUEST_RECEIVED
57from acts_contrib.test_utils.tel.tel_defines import CallStateContainer
58from acts_contrib.test_utils.tel.tel_subscription_utils import get_outgoing_voice_sub_id
59from acts_contrib.test_utils.tel.tel_subscription_utils import get_incoming_voice_sub_id
60from acts_contrib.test_utils.tel.tel_test_utils import call_setup_teardown_for_subscription
61from acts_contrib.test_utils.tel.tel_test_utils import ensure_network_generation
62from acts_contrib.test_utils.tel.tel_test_utils import is_event_match
63from acts_contrib.test_utils.tel.tel_test_utils import hangup_call
64from acts_contrib.test_utils.tel.tel_test_utils import initiate_call
65from acts_contrib.test_utils.tel.tel_test_utils import set_wfc_mode_for_subscription
66from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode
67from acts_contrib.test_utils.tel.tel_test_utils import toggle_volte
68from acts_contrib.test_utils.tel.tel_test_utils import verify_incall_state
69from acts_contrib.test_utils.tel.tel_test_utils import wait_and_answer_call_for_subscription
70from acts_contrib.test_utils.tel.tel_test_utils import wait_for_network_generation
71from acts_contrib.test_utils.tel.tel_test_utils import wait_for_network_rat_for_subscription
72from acts_contrib.test_utils.tel.tel_test_utils import wait_for_ringing_call
73from acts_contrib.test_utils.tel.tel_test_utils import wait_for_telecom_ringing
74from acts_contrib.test_utils.tel.tel_test_utils import wait_for_video_enabled
75from acts_contrib.test_utils.tel.tel_test_utils import get_network_rat
76from acts_contrib.test_utils.tel.tel_test_utils import is_wfc_enabled
77from acts_contrib.test_utils.tel.tel_voice_utils import is_call_hd
78from acts_contrib.test_utils.tel.tel_voice_utils import phone_setup_iwlan_for_subscription
79
80
81def phone_setup_video(
82    log,
83    ad,
84    wfc_mode=WFC_MODE_DISABLED,
85    is_airplane_mode=False,
86    wifi_ssid=None,
87    wifi_pwd=None):
88    """Setup phone default sub_id to make video call
89
90    Args:
91        log: log object.
92        ad: android device object
93        wfc_mode: WFC mode to set to.
94            Valid mode includes: WFC_MODE_WIFI_ONLY, WFC_MODE_CELLULAR_PREFERRED,
95            WFC_MODE_WIFI_PREFERRED, WFC_MODE_DISABLED.
96
97    Returns:
98        True if ad (default sub_id) is setup correctly and idle for video call.
99    """
100    return phone_setup_video_for_subscription(log, ad,
101                                              get_outgoing_voice_sub_id(ad),
102                                              wfc_mode,
103                                              False,
104                                              wifi_ssid,
105                                              wifi_pwd)
106
107
108def phone_setup_video_for_subscription(log,
109                                       ad,
110                                       sub_id,
111                                       wfc_mode=WFC_MODE_DISABLED,
112                                       is_airplane_mode=False,
113                                       wifi_ssid=None,
114                                       wifi_pwd=None):
115    """Setup phone sub_id to make video call
116
117    Args:
118        log: log object.
119        ad: android device object
120        sub_id: ad's sub id.
121        wfc_mode: WFC mode to set to. Valid mode includes:
122            - WFC_MODE_WIFI_ONLY
123                - Wi-Fi will be connected if wifi_ssid is assigned.
124            - WFC_MODE_CELLULAR_PREFERRED
125                - Wi-Fi will be connected if wifi_ssid is assigned.
126            - WFC_MODE_WIFI_PREFERRED
127                - Wi-Fi will be connected if wifi_ssid is assigned.
128            - WFC_MODE_DISABLED
129                - Only WFC mode will be set to DISABLED.
130            - None
131                - Neither WFC mode nor Wi-Fi state will be changed.
132        is_airplane_mode:
133            - False: airplane mode disabled
134            - True: airplane mode enabled for ViWifi
135        wifi_ssid: SSID of Wi-Fi AP to connect for ViWifi
136        wifi_ssid: Password of Wi-Fi AP SSID for ViWifi
137
138    Returns:
139        True if ad (sub_id) is setup correctly and idle for video call.
140    """
141    if not ensure_network_generation(
142            log, ad, GEN_4G, voice_or_data=NETWORK_SERVICE_DATA):
143        log.error("{} voice not in LTE mode.".format(ad.serial))
144        return False
145
146    toggle_volte(log, ad, True)
147
148    if wfc_mode == WFC_MODE_DISABLED:
149        if not set_wfc_mode_for_subscription(ad, wfc_mode, sub_id):
150            log.error("{} WFC mode failed to be set to {}.".format(
151                ad.serial, wfc_mode))
152            return False
153    else:
154        if wfc_mode:
155            if not phone_setup_iwlan_for_subscription(log, ad, sub_id,
156                is_airplane_mode, wfc_mode, wifi_ssid, wifi_pwd):
157                log.error("Failed to set up phone on iwlan.")
158                return False
159
160    return phone_idle_video_for_subscription(log, ad, sub_id)
161
162
163def phone_idle_video(log, ad):
164    """Return if phone (default sub_id) is idle for video call.
165
166    Args:
167        log: log object.
168        ad: android device object
169
170    Returns:
171        True if ad is idle for video call.
172    """
173    return phone_idle_video_for_subscription(log, ad,
174                                             get_outgoing_voice_sub_id(ad))
175
176
177def phone_idle_video_for_subscription(log, ad, sub_id):
178    """Return if phone (sub_id) is idle for video call.
179
180    Args:
181        log: log object.
182        ad: android device object
183        sub_id: ad's sub id
184
185    Returns:
186        True if ad (sub_id) is idle for video call.
187    """
188
189    if not wait_for_network_generation(log, ad, GEN_4G):
190        log.error("{} voice not in LTE mode.".format(ad.serial))
191        return False
192
193    if not wait_for_video_enabled(log, ad, MAX_WAIT_TIME_VOLTE_ENABLED):
194        log.error(
195            "{} failed to <report video calling enabled> within {}s.".format(
196                ad.serial, MAX_WAIT_TIME_VOLTE_ENABLED))
197        return False
198    return True
199
200
201def is_phone_in_call_video(log, ad):
202    """Return if ad is in a video call (in expected video state).
203
204    Args:
205        log: log object.
206        ad: android device object
207        video_state: Expected Video call state.
208            This is optional, if it's None,
209            then TX_ENABLED/RX_ENABLED/BIDIRECTIONAL video call state will
210            return True.
211
212    Returns:
213        True if ad (for sub_id) is in a video call (in expected video state).
214    """
215    return is_phone_in_call_video_for_subscription(
216        log, ad, get_outgoing_voice_sub_id(ad))
217
218
219def is_phone_in_call_video_for_subscription(log, ad, sub_id, video_state=None):
220    """Return if ad (for sub_id) is in a video call (in expected video state).
221    Args:
222        log: log object.
223        ad: android device object
224        sub_id: device sub_id
225        video_state: Expected Video call state.
226            This is optional, if it's None,
227            then TX_ENABLED/RX_ENABLED/BIDIRECTIONAL video call state will
228            return True.
229
230    Returns:
231        True if ad is in a video call (in expected video state).
232    """
233
234    if video_state is None:
235        log.info("Verify if {}(subid {}) in video call.".format(
236            ad.serial, sub_id))
237    if not ad.droid.telecomIsInCall():
238        log.error("{} not in call.".format(ad.serial))
239        return False
240    call_list = ad.droid.telecomCallGetCallIds()
241    for call in call_list:
242        state = ad.droid.telecomCallVideoGetState(call)
243        if video_state is None:
244            if {
245                    VT_STATE_AUDIO_ONLY: False,
246                    VT_STATE_TX_ENABLED: True,
247                    VT_STATE_TX_PAUSED: True,
248                    VT_STATE_RX_ENABLED: True,
249                    VT_STATE_RX_PAUSED: True,
250                    VT_STATE_BIDIRECTIONAL: True,
251                    VT_STATE_BIDIRECTIONAL_PAUSED: True,
252                    VT_STATE_STATE_INVALID: False
253            }[state]:
254                return True
255        else:
256            if state == video_state:
257                return True
258        log.info("Non-Video-State: {}".format(state))
259    log.error("Phone not in video call. Call list: {}".format(call_list))
260    return False
261
262
263def is_phone_in_call_viwifi_for_subscription(log, ad, sub_id,
264                                             video_state=None):
265    """Return if ad (for sub_id) is in a viwifi call (in expected video state).
266    Args:
267        log: log object.
268        ad: android device object
269        sub_id: device sub_id
270        video_state: Expected Video call state.
271            This is optional, if it's None,
272            then TX_ENABLED/RX_ENABLED/BIDIRECTIONAL video call state will
273            return True.
274
275    Returns:
276        True if ad is in a video call (in expected video state).
277    """
278
279    if video_state is None:
280        log.info("Verify if {}(subid {}) in video call.".format(
281            ad.serial, sub_id))
282    if not ad.droid.telecomIsInCall():
283        log.error("{} not in call.".format(ad.serial))
284        return False
285    nw_type = get_network_rat(log, ad, NETWORK_SERVICE_DATA)
286    if nw_type != RAT_IWLAN:
287        ad.log.error("Data rat on: %s. Expected: iwlan", nw_type)
288        return False
289    if not is_wfc_enabled(log, ad):
290        ad.log.error("WiFi Calling feature bit is False.")
291        return False
292    call_list = ad.droid.telecomCallGetCallIds()
293    for call in call_list:
294        state = ad.droid.telecomCallVideoGetState(call)
295        if video_state is None:
296            if {
297                    VT_STATE_AUDIO_ONLY: False,
298                    VT_STATE_TX_ENABLED: True,
299                    VT_STATE_TX_PAUSED: True,
300                    VT_STATE_RX_ENABLED: True,
301                    VT_STATE_RX_PAUSED: True,
302                    VT_STATE_BIDIRECTIONAL: True,
303                    VT_STATE_BIDIRECTIONAL_PAUSED: True,
304                    VT_STATE_STATE_INVALID: False
305            }[state]:
306                return True
307        else:
308            if state == video_state:
309                return True
310        ad.log.info("Non-Video-State: %s", state)
311    ad.log.error("Phone not in video call. Call list: %s", call_list)
312    return False
313
314
315def is_phone_in_call_video_bidirectional(log, ad):
316    """Return if phone in bi-directional video call.
317
318    Args:
319        log: log object.
320        ad: android device object
321
322    Returns:
323        True if phone in bi-directional video call.
324    """
325    return is_phone_in_call_video_bidirectional_for_subscription(
326        log, ad, get_outgoing_voice_sub_id(ad))
327
328
329def is_phone_in_call_video_bidirectional_for_subscription(log, ad, sub_id):
330    """Return if phone in bi-directional video call for subscription id.
331
332    Args:
333        log: log object.
334        ad: android device object
335        sub_id: subscription id.
336
337    Returns:
338        True if phone in bi-directional video call.
339    """
340    log.info("Verify if {}(subid {}) in bi-directional video call.".format(
341        ad.serial, sub_id))
342    return is_phone_in_call_video_for_subscription(log, ad, sub_id,
343                                                   VT_STATE_BIDIRECTIONAL)
344
345
346def is_phone_in_call_viwifi_bidirectional(log, ad):
347    """Return if phone in bi-directional viwifi call.
348
349    Args:
350        log: log object.
351        ad: android device object
352
353    Returns:
354        True if phone in bi-directional viwifi call.
355    """
356    return is_phone_in_call_viwifi_bidirectional_for_subscription(
357        log, ad, get_outgoing_voice_sub_id(ad))
358
359
360def is_phone_in_call_viwifi_bidirectional_for_subscription(log, ad, sub_id):
361    """Return if phone in bi-directional viwifi call for subscription id.
362
363    Args:
364        log: log object.
365        ad: android device object
366        sub_id: subscription id.
367
368    Returns:
369        True if phone in bi-directional viwifi call.
370    """
371    ad.log.info("Verify if subid %s in bi-directional video call.", sub_id)
372    return is_phone_in_call_viwifi_for_subscription(log, ad, sub_id,
373                                                    VT_STATE_BIDIRECTIONAL)
374
375
376def is_phone_in_call_video_tx_enabled(log, ad):
377    """Return if phone in tx_enabled video call.
378
379    Args:
380        log: log object.
381        ad: android device object
382
383    Returns:
384        True if phone in tx_enabled video call.
385    """
386    return is_phone_in_call_video_tx_enabled_for_subscription(
387        log, ad, get_outgoing_voice_sub_id(ad))
388
389
390def is_phone_in_call_video_tx_enabled_for_subscription(log, ad, sub_id):
391    """Return if phone in tx_enabled video call for subscription id.
392
393    Args:
394        log: log object.
395        ad: android device object
396        sub_id: subscription id.
397
398    Returns:
399        True if phone in tx_enabled video call.
400    """
401    log.info("Verify if {}(subid {}) in tx_enabled video call.".format(
402        ad.serial, sub_id))
403    return is_phone_in_call_video_for_subscription(log, ad, sub_id,
404                                                   VT_STATE_TX_ENABLED)
405
406
407def is_phone_in_call_video_rx_enabled(log, ad):
408    """Return if phone in rx_enabled video call.
409
410    Args:
411        log: log object.
412        ad: android device object
413
414    Returns:
415        True if phone in rx_enabled video call.
416    """
417    return is_phone_in_call_video_rx_enabled_for_subscription(
418        log, ad, get_outgoing_voice_sub_id(ad))
419
420
421def is_phone_in_call_video_rx_enabled_for_subscription(log, ad, sub_id):
422    """Return if phone in rx_enabled video call for subscription id.
423
424    Args:
425        log: log object.
426        ad: android device object
427        sub_id: subscription id.
428
429    Returns:
430        True if phone in rx_enabled video call.
431    """
432    log.info("Verify if {}(subid {}) in rx_enabled video call.".format(
433        ad.serial, sub_id))
434    return is_phone_in_call_video_for_subscription(log, ad, sub_id,
435                                                   VT_STATE_RX_ENABLED)
436
437
438def is_phone_in_call_voice_hd(log, ad):
439    """Return if phone in hd voice call.
440
441    Args:
442        log: log object.
443        ad: android device object
444
445    Returns:
446        True if phone in hd voice call.
447    """
448    return is_phone_in_call_voice_hd_for_subscription(
449        log, ad, get_outgoing_voice_sub_id(ad))
450
451
452def is_phone_in_call_voice_hd_for_subscription(log, ad, sub_id):
453    """Return if phone in hd voice call for subscription id.
454
455    Args:
456        log: log object.
457        ad: android device object
458        sub_id: subscription id.
459
460    Returns:
461        True if phone in hd voice call.
462    """
463    log.info("Verify if {}(subid {}) in hd voice call.".format(
464        ad.serial, sub_id))
465    if not ad.droid.telecomIsInCall():
466        log.error("{} not in call.".format(ad.serial))
467        return False
468    for call in ad.droid.telecomCallGetCallIds():
469        state = ad.droid.telecomCallVideoGetState(call)
470        if (state == VT_STATE_AUDIO_ONLY and is_call_hd(log, ad, call)):
471            return True
472        log.info("Non-HDAudio-State: {}, property: {}".format(
473            state, ad.droid.telecomCallGetProperties(call)))
474    return False
475
476
477def initiate_video_call(log, ad_caller, callee_number):
478    """Make phone call from caller to callee.
479
480    Args:
481        log: logging handle
482        ad_caller: Caller android device object.
483        callee_number: Callee phone number.
484
485    Returns:
486        result: if phone call is placed successfully.
487    """
488    return initiate_call(log, ad_caller, callee_number, video=True)
489
490
491def wait_and_answer_video_call(log,
492                               ad,
493                               incoming_number=None,
494                               video_state=VT_STATE_BIDIRECTIONAL,
495                               incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND):
496    """Wait for an incoming call on default voice subscription and
497       accepts the call.
498
499    Args:
500        ad: android device object.
501        incoming_number: Expected incoming number.
502            Optional. Default is None
503        incall_ui_display: after answer the call, bring in-call UI to foreground or
504            background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND.
505            if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground.
506            if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background.
507            else, do nothing.
508
509    Returns:
510        True: if incoming call is received and answered successfully.
511        False: for errors
512    """
513    return wait_and_answer_video_call_for_subscription(
514        log, ad, get_outgoing_voice_sub_id(ad), incoming_number, video_state,
515        incall_ui_display)
516
517
518def wait_and_answer_video_call_for_subscription(
519        log,
520        ad,
521        sub_id,
522        incoming_number=None,
523        video_state=VT_STATE_BIDIRECTIONAL,
524        incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND):
525    """Wait for an incoming call on specified subscription and
526       accepts the call.
527
528    Args:
529        ad: android device object.
530        sub_id: subscription ID
531        incoming_number: Expected incoming number.
532            Optional. Default is None
533        incall_ui_display: after answer the call, bring in-call UI to foreground or
534            background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND.
535            if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground.
536            if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background.
537            else, do nothing.
538
539    Returns:
540        True: if incoming call is received and answered successfully.
541        False: for errors
542    """
543    return wait_and_answer_call_for_subscription(
544        log,
545        ad,
546        sub_id,
547        incoming_number=None,
548        incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND,
549        video_state=video_state)
550
551
552def video_call_setup_teardown(log,
553                              ad_caller,
554                              ad_callee,
555                              ad_hangup=None,
556                              video_state=VT_STATE_BIDIRECTIONAL,
557                              verify_caller_func=None,
558                              verify_callee_func=None,
559                              wait_time_in_call=WAIT_TIME_IN_CALL,
560                              incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND):
561    """ Call process, including make a phone call from caller,
562    accept from callee, and hang up. The call is on default subscription
563
564    In call process, call from <droid_caller> to <droid_callee>,
565    accept the call, (optional)then hang up from <droid_hangup>.
566
567    Args:
568        ad_caller: Caller Android Device Object.
569        ad_callee: Callee Android Device Object.
570        ad_hangup: Android Device Object end the phone call.
571            Optional. Default value is None, and phone call will continue.
572        video_state: video state for VT call.
573            Optional. Default value is VT_STATE_BIDIRECTIONAL
574        verify_caller_func: func_ptr to verify caller in correct mode
575            Optional. Default is None
576        verify_callee_func: func_ptr to verify callee in correct mode
577            Optional. Default is None
578        wait_time_in_call: wait time during call.
579            Optional. Default is WAIT_TIME_IN_CALL.
580        incall_ui_display: after answer the call, bring in-call UI to foreground or
581            background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND.
582            if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground.
583            if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background.
584            else, do nothing.
585
586    Returns:
587        True if call process without any error.
588        False if error happened.
589
590    """
591    return video_call_setup_teardown_for_subscription(
592        log, ad_caller, ad_callee, get_outgoing_voice_sub_id(ad_caller),
593        get_incoming_voice_sub_id(ad_callee), ad_hangup, video_state,
594        verify_caller_func, verify_callee_func, wait_time_in_call,
595        incall_ui_display)
596
597
598def video_call_setup_teardown_for_subscription(
599        log,
600        ad_caller,
601        ad_callee,
602        subid_caller,
603        subid_callee,
604        ad_hangup=None,
605        video_state=VT_STATE_BIDIRECTIONAL,
606        verify_caller_func=None,
607        verify_callee_func=None,
608        wait_time_in_call=WAIT_TIME_IN_CALL,
609        incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND):
610    """ Call process, including make a phone call from caller,
611    accept from callee, and hang up. The call is on specified subscription
612
613    In call process, call from <droid_caller> to <droid_callee>,
614    accept the call, (optional)then hang up from <droid_hangup>.
615
616    Args:
617        ad_caller: Caller Android Device Object.
618        ad_callee: Callee Android Device Object.
619        subid_caller: Caller subscription ID
620        subid_callee: Callee subscription ID
621        ad_hangup: Android Device Object end the phone call.
622            Optional. Default value is None, and phone call will continue.
623        video_state: video state for VT call.
624            Optional. Default value is VT_STATE_BIDIRECTIONAL
625        verify_caller_func: func_ptr to verify caller in correct mode
626            Optional. Default is None
627        verify_callee_func: func_ptr to verify callee in correct mode
628            Optional. Default is None
629        wait_time_in_call: wait time during call.
630            Optional. Default is WAIT_TIME_IN_CALL.
631        incall_ui_display: after answer the call, bring in-call UI to foreground or
632            background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND.
633            if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground.
634            if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background.
635            else, do nothing.
636
637    Returns:
638        True if call process without any error.
639        False if error happened.
640
641    """
642    return call_setup_teardown_for_subscription(
643        log,
644        ad_caller,
645        ad_callee,
646        subid_caller,
647        subid_callee,
648        ad_hangup=ad_hangup,
649        verify_caller_func=verify_caller_func,
650        verify_callee_func=verify_callee_func,
651        wait_time_in_call=wait_time_in_call,
652        incall_ui_display=incall_ui_display,
653        video_state=video_state)
654
655
656def video_call_setup(log,
657                     ad_caller,
658                     ad_callee,
659                     video_state=VT_STATE_BIDIRECTIONAL,
660                     incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND):
661    """ Call process, including make a phone call from caller,
662    accept from callee, and hang up. The call is on default subscription
663
664    In call process, call from <droid_caller> to <droid_callee>,
665    accept the call, (optional)then hang up from <droid_hangup>.
666
667    Args:
668        ad_caller: Caller Android Device Object.
669        ad_callee: Callee Android Device Object.
670        incall_ui_display: after answer the call, bring in-call UI to foreground or
671            background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND.
672            if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground.
673            if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background.
674            else, do nothing.
675
676    Returns:
677        True if call process without any error.
678        False if error happened.
679
680    """
681    return video_call_setup_for_subscription(
682        log, ad_caller, ad_callee, get_outgoing_voice_sub_id(ad_caller),
683        get_incoming_voice_sub_id(ad_callee), video_state, incall_ui_display)
684
685
686def video_call_setup_for_subscription(
687        log,
688        ad_caller,
689        ad_callee,
690        subid_caller,
691        subid_callee,
692        video_state=VT_STATE_BIDIRECTIONAL,
693        incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND):
694    """ Call process, including make a phone call from caller,
695    accept from callee, and hang up. The call is on specified subscription
696
697    In call process, call from <droid_caller> to <droid_callee>,
698    accept the call, (optional)then hang up from <droid_hangup>.
699
700    Args:
701        ad_caller: Caller Android Device Object.
702        ad_callee: Callee Android Device Object.
703        subid_caller: Caller subscription ID
704        subid_callee: Callee subscription ID
705        ad_hangup: Android Device Object end the phone call.
706            Optional. Default value is None, and phone call will continue.
707        incall_ui_display: after answer the call, bring in-call UI to foreground or
708            background. Optional, default value is INCALL_UI_DISPLAY_FOREGROUND.
709            if = INCALL_UI_DISPLAY_FOREGROUND, bring in-call UI to foreground.
710            if = INCALL_UI_DISPLAY_BACKGROUND, bring in-call UI to background.
711            else, do nothing.
712
713    Returns:
714        True if call process without any error.
715        False if error happened.
716
717    """
718    return call_setup_teardown_for_subscription(
719        log,
720        ad_caller,
721        ad_callee,
722        subid_caller,
723        subid_callee,
724        ad_hangup=None,
725        incall_ui_display=incall_ui_display,
726        video_state=video_state)
727
728
729def video_call_modify_video(log,
730                            ad_requester,
731                            call_id_requester,
732                            ad_responder,
733                            call_id_responder,
734                            video_state_request,
735                            video_quality_request=VT_VIDEO_QUALITY_DEFAULT,
736                            video_state_response=None,
737                            video_quality_response=None,
738                            verify_func_between_request_and_response=None):
739    """Modifies an ongoing call to change the video_call state
740
741    Args:
742        log: logger object
743        ad_requester: android_device object of the requester
744        call_id_requester: the call_id of the call placing the modify request
745        ad_requester: android_device object of the responder
746        call_id_requester: the call_id of the call receiving the modify request
747        video_state_request: the requested video state
748        video_quality_request: the requested video quality, defaults to
749            QUALITY_DEFAULT
750        video_state_response: the responded video state or, or (default)
751            match the request if None
752        video_quality_response: the responded video quality, or (default)
753            match the request if None
754
755    Returns:
756        A call_id corresponding to the first call in the state, or None
757    """
758
759    if not video_state_response:
760        video_state_response = video_state_request
761    if not video_quality_response:
762        video_quality_response = video_quality_request
763
764    cur_video_state = ad_requester.droid.telecomCallVideoGetState(
765        call_id_requester)
766
767    log.info("State change request from {} to {} requested".format(
768        cur_video_state, video_state_request))
769
770    if cur_video_state == video_state_request:
771        return True
772
773    ad_responder.ed.clear_events(
774        EventTelecomVideoCallSessionModifyRequestReceived)
775
776    ad_responder.droid.telecomCallVideoStartListeningForEvent(
777        call_id_responder, EVENT_VIDEO_SESSION_MODIFY_REQUEST_RECEIVED)
778
779    ad_requester.droid.telecomCallVideoSendSessionModifyRequest(
780        call_id_requester, video_state_request, video_quality_request)
781
782    try:
783        request_event = ad_responder.ed.pop_event(
784            EventTelecomVideoCallSessionModifyRequestReceived,
785            MAX_WAIT_TIME_VIDEO_SESSION_EVENT)
786        log.info(request_event)
787    except Empty:
788        log.error("Failed to receive SessionModifyRequest!")
789        return False
790    finally:
791        ad_responder.droid.telecomCallVideoStopListeningForEvent(
792            call_id_responder, EVENT_VIDEO_SESSION_MODIFY_REQUEST_RECEIVED)
793
794    if (verify_func_between_request_and_response
795            and not verify_func_between_request_and_response()):
796        log.error("verify_func_between_request_and_response failed.")
797        return False
798
799    # TODO: b/26291165 Replace with reducing the volume as we want
800    # to test route switching
801    ad_requester.droid.telecomCallSetAudioRoute(AUDIO_ROUTE_EARPIECE)
802
803    ad_requester.droid.telecomCallVideoStartListeningForEvent(
804        call_id_requester, EVENT_VIDEO_SESSION_MODIFY_RESPONSE_RECEIVED)
805
806    ad_responder.droid.telecomCallVideoSendSessionModifyResponse(
807        call_id_responder, video_state_response, video_quality_response)
808
809    try:
810        response_event = ad_requester.ed.pop_event(
811            EventTelecomVideoCallSessionModifyResponseReceived,
812            MAX_WAIT_TIME_VIDEO_SESSION_EVENT)
813        log.info(response_event)
814    except Empty:
815        log.error("Failed to receive SessionModifyResponse!")
816        return False
817    finally:
818        ad_requester.droid.telecomCallVideoStopListeningForEvent(
819            call_id_requester, EVENT_VIDEO_SESSION_MODIFY_RESPONSE_RECEIVED)
820
821    # TODO: b/26291165 Replace with reducing the volume as we want
822    # to test route switching
823    ad_responder.droid.telecomCallSetAudioRoute(AUDIO_ROUTE_EARPIECE)
824
825    return True
826
827
828def is_call_id_in_video_state(log, ad, call_id, video_state):
829    """Return is the call_id is in expected video_state
830
831    Args:
832        log: logger object
833        ad: android_device object
834        call_id: call id
835        video_state: valid VIDEO_STATE
836
837    Returns:
838        True is call_id in expected video_state; False if not.
839    """
840    return video_state == ad.droid.telecomCallVideoGetState(call_id)
841
842
843def get_call_id_in_video_state(log, ad, video_state):
844    """Gets the first call reporting a given video_state
845        from among the active calls
846
847    Args:
848        log: logger object
849        ad: android_device object
850        video_state: valid VIDEO_STATE
851
852    Returns:
853        A call_id corresponding to the first call in the state, or None
854    """
855
856    if not ad.droid.telecomIsInCall():
857        log.error("{} not in call.".format(ad.serial))
858        return None
859    for call in ad.droid.telecomCallGetCallIds():
860        if is_call_id_in_video_state(log, ad, call, video_state):
861            return call
862    return None
863
864
865def video_call_downgrade(log,
866                         ad_requester,
867                         call_id_requester,
868                         ad_responder,
869                         call_id_responder,
870                         video_state_request=None,
871                         video_quality_request=VT_VIDEO_QUALITY_DEFAULT):
872    """Downgrade Video call to video_state_request.
873    Send telecomCallVideoSendSessionModifyRequest from ad_requester.
874    Get video call state from ad_requester and ad_responder.
875    Verify video calls states are correct and downgrade succeed.
876
877    Args:
878        log: logger object
879        ad_requester: android_device object of the requester
880        call_id_requester: the call_id of the call placing the modify request
881        ad_requester: android_device object of the responder
882        call_id_requester: the call_id of the call receiving the modify request
883        video_state_request: the requested downgrade video state
884            This parameter is optional. If this parameter is None:
885                if call_id_requester current is bi-directional, will downgrade to RX_ENABLED
886                if call_id_requester current is RX_ENABLED, will downgrade to AUDIO_ONLY
887        video_quality_request: the requested video quality, defaults to
888            QUALITY_DEFAULT
889    Returns:
890        True if downgrade succeed.
891    """
892    if (call_id_requester is None) or (call_id_responder is None):
893        log.error("call_id_requester: {}, call_id_responder: {}".format(
894            call_id_requester, call_id_responder))
895        return False
896    current_video_state_requester = ad_requester.droid.telecomCallVideoGetState(
897        call_id_requester)
898    if video_state_request is None:
899        if (current_video_state_requester == VT_STATE_BIDIRECTIONAL or
900                current_video_state_requester == VT_STATE_BIDIRECTIONAL_PAUSED
901            ):
902            video_state_request = VT_STATE_RX_ENABLED
903        elif (current_video_state_requester == VT_STATE_TX_ENABLED
904              or current_video_state_requester == VT_STATE_TX_PAUSED):
905            video_state_request = VT_STATE_AUDIO_ONLY
906        else:
907            log.error("Can Not Downgrade. ad: {}, current state {}".format(
908                ad_requester.serial, current_video_state_requester))
909            return False
910    expected_video_state_responder = {
911        VT_STATE_AUDIO_ONLY: VT_STATE_AUDIO_ONLY,
912        VT_STATE_RX_ENABLED: VT_STATE_TX_ENABLED
913    }[video_state_request]
914
915    ad_requester.droid.telecomCallVideoStartListeningForEvent(
916        call_id_requester, EVENT_VIDEO_SESSION_MODIFY_RESPONSE_RECEIVED)
917
918    ad_requester.droid.telecomCallVideoSendSessionModifyRequest(
919        call_id_requester, video_state_request, video_quality_request)
920
921    try:
922        response_event = ad_requester.ed.pop_event(
923            EventTelecomVideoCallSessionModifyResponseReceived,
924            MAX_WAIT_TIME_VIDEO_SESSION_EVENT)
925        log.info(response_event)
926    except Empty:
927        log.error("Failed to receive SessionModifyResponse!")
928        return False
929    finally:
930        ad_requester.droid.telecomCallVideoStopListeningForEvent(
931            call_id_requester, EVENT_VIDEO_SESSION_MODIFY_RESPONSE_RECEIVED)
932
933    time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING)
934    # TODO: b/26291165 Replace with reducing the volume as we want
935    # to test route switching
936    ad_requester.droid.telecomCallSetAudioRoute(AUDIO_ROUTE_EARPIECE)
937    ad_responder.droid.telecomCallSetAudioRoute(AUDIO_ROUTE_EARPIECE)
938
939    time.sleep(WAIT_TIME_IN_CALL)
940    if video_state_request != ad_requester.droid.telecomCallVideoGetState(
941            call_id_requester):
942        log.error("requester not in correct state. expected:{}, current:{}"
943                  .format(video_state_request,
944                          ad_requester.droid.telecomCallVideoGetState(
945                              call_id_requester)))
946        return False
947    if (expected_video_state_responder !=
948            ad_responder.droid.telecomCallVideoGetState(call_id_responder)):
949        log.error(
950            "responder not in correct state. expected:{}, current:{}".format(
951                expected_video_state_responder,
952                ad_responder.droid.telecomCallVideoGetState(
953                    call_id_responder)))
954        return False
955
956    return True
957
958
959def verify_video_call_in_expected_state(log, ad, call_id, call_video_state,
960                                        call_state):
961    """Return True if video call is in expected video state and call state.
962
963    Args:
964        log: logger object
965        ad: android_device object
966        call_id: ad's call id
967        call_video_state: video state to validate.
968        call_state: call state to validate.
969
970    Returns:
971        True if video call is in expected video state and call state.
972    """
973    if not is_call_id_in_video_state(log, ad, call_id, call_video_state):
974        log.error("Call is not in expected {} state. Current state {}".format(
975            call_video_state, ad.droid.telecomCallVideoGetState(call_id)))
976        return False
977    if ad.droid.telecomCallGetCallState(call_id) != call_state:
978        log.error("Call is not in expected {} state. Current state {}".format(
979            call_state, ad.droid.telecomCallGetCallState(call_id)))
980        return False
981    return True
982