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