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