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