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