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