1# Copyright (C) 2024 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""HFP proxy module.""" 15 16import sys 17import threading 18import time 19 20from mmi2grpc._helpers import assert_description, match_description 21from mmi2grpc._proxy import ProfileProxy 22from pandora.host_grpc import Host 23from pandora.host_pb2 import CONNECTABLE, DISCOVERABLE_GENERAL 24from pandora.security_grpc import Security, SecurityStorage 25from pandora.security_pb2 import PairingEventAnswer 26from pandora_experimental.hfp_grpc import HFP 27from pandora_experimental.hfp_pb2 import (AUDIO_PATH_HANDSFREE, AUDIO_PATH_SPEAKERS) 28 29# Standard time to wait before asking for waitConnection 30WAIT_DELAY_BEFORE_CONNECTION = 2 31 32IXIT_PHONE_NUMBER = 42 33IXIT_SECOND_PHONE_NUMBER = 43 34 35 36class HFPProxy(ProfileProxy): 37 38 def __init__(self, test, channel, rootcanal, modem): 39 super().__init__(channel) 40 self.hfp = HFP(channel) 41 self.host = Host(channel) 42 self.security = Security(channel) 43 self.security_storage = SecurityStorage(channel) 44 self.rootcanal = rootcanal 45 self.modem = modem 46 self.connection = None 47 48 self._auto_confirm_requests() 49 50 def asyncWaitConnection(self, pts_addr, delay=WAIT_DELAY_BEFORE_CONNECTION): 51 """ 52 Send a WaitConnection in a grpc callback 53 """ 54 55 def waitConnectionCallback(self, pts_addr): 56 self.connection = self.host.WaitConnection(address=pts_addr).connection 57 58 print(f"HFP placeholder mmi: asyncWaitConnection", file=sys.stderr) 59 th = threading.Timer(interval=delay, function=waitConnectionCallback, args=(self, pts_addr)) 60 th.start() 61 62 def test_started(self, test: str, pts_addr: bytes, **kwargs): 63 if test not in ("HFP/AG/SLC/BV-02-C", "HFP/AG/SLC/BV-04-C"): 64 self.asyncWaitConnection(pts_addr) 65 66 return "OK" 67 68 @assert_description 69 def TSC_delete_pairing_iut(self, pts_addr: bytes, **kwargs): 70 """ 71 Delete the pairing with the PTS using the Implementation Under Test 72 (IUT), then click Ok. 73 """ 74 75 self.security_storage.DeleteBond(public=pts_addr) 76 return "OK" 77 78 @assert_description 79 def TSC_iut_enable_slc(self, test: str, pts_addr: bytes, **kwargs): 80 """ 81 Click Ok, then initiate a service level connection from the 82 Implementation Under Test (IUT) to the PTS. 83 """ 84 85 def enable_slc(): 86 time.sleep(2) 87 88 if not self.connection: 89 self.connection = self.host.Connect(address=pts_addr).connection 90 91 if "HFP/HF" in test: 92 self.hfp.EnableSlcAsHandsfree(connection=self.connection) 93 else: 94 self.hfp.EnableSlc(connection=self.connection) 95 96 threading.Thread(target=enable_slc).start() 97 98 return "OK" 99 100 @assert_description 101 def TSC_iut_search(self, **kwargs): 102 """ 103 Using the Implementation Under Test (IUT), perform a search for the PTS. 104 If found, click OK. 105 """ 106 107 return "OK" 108 109 @assert_description 110 def TSC_iut_connect(self, pts_addr: bytes, **kwargs): 111 """ 112 Click Ok, then make a connection request to the PTS from the 113 Implementation Under Test (IUT). 114 """ 115 116 def connect(): 117 time.sleep(2) 118 self.connection = self.host.Connect(address=pts_addr).connection 119 120 threading.Thread(target=connect).start() 121 122 return "OK" 123 124 @assert_description 125 def TSC_iut_connectable(self, pts_addr: str, test: str, **kwargs): 126 """ 127 Make the Implementation Under Test (IUT) connectable, then click Ok. 128 """ 129 130 self.host.SetConnectabilityMode(mode=CONNECTABLE) 131 # these two test cases fail if Connection is established in "TSC_iut_enable_slc" 132 if test in ("HFP/AG/SLC/BV-02-C", "HFP/AG/SLC/BV-04-C"): 133 self.connection = self.host.Connect(address=pts_addr).connection 134 135 return "OK" 136 137 @assert_description 138 def TSC_iut_disable_slc(self, test: str, pts_addr: bytes, **kwargs): 139 """ 140 Click Ok, then disable the service level connection using the 141 Implementation Under Test (IUT). 142 """ 143 144 def disable_slc(): 145 time.sleep(2) 146 if "HFP/HF" in test: 147 self.hfp.DisableSlcAsHandsfree(connection=self.connection) 148 else: 149 self.hfp.DisableSlc(connection=self.connection) 150 151 threading.Thread(target=disable_slc).start() 152 153 return "OK" 154 155 @assert_description 156 def TSC_make_battery_charged(self, **kwargs): 157 """ 158 Click Ok, then manipulate the Implementation Under Test (IUT) so that 159 the battery is fully charged. 160 """ 161 162 self.hfp.SetBatteryLevel(connection=self.connection, battery_percentage=100) 163 164 return "OK" 165 166 @assert_description 167 def TSC_make_battery_discharged(self, **kwargs): 168 """ 169 Manipulate the Implementation Under Test (IUT) so that the battery level 170 is not fully charged, then click Ok. 171 """ 172 173 self.hfp.SetBatteryLevel(connection=self.connection, battery_percentage=42) 174 175 return "OK" 176 177 @assert_description 178 def TSC_ag_iut_enable_call(self, **kwargs): 179 """ 180 Click Ok, then place a call from an external line to the Implementation 181 Under Test (IUT). Do not answer the call unless prompted to do so. 182 """ 183 184 def enable_call(): 185 time.sleep(2) 186 self.modem.call(IXIT_PHONE_NUMBER) 187 188 threading.Thread(target=enable_call).start() 189 190 return "OK" 191 192 @assert_description 193 def TSC_verify_audio(self, **kwargs): 194 """ 195 Verify the presence of an audio connection, then click Ok. 196 """ 197 198 # TODO 199 time.sleep(2) # give it time for SCO to come up 200 201 return "OK" 202 203 @assert_description 204 def TSC_ag_iut_disable_call_external(self, **kwargs): 205 """ 206 Click Ok, then end the call using the external terminal. 207 """ 208 209 def disable_call_external(): 210 time.sleep(2) 211 self.hfp.DeclineCall() 212 213 threading.Thread(target=disable_call_external).start() 214 215 return "OK" 216 217 @assert_description 218 def TSC_iut_enable_audio_using_codec(self, **kwargs): 219 """ 220 Click OK, then initiate an audio connection using the Codec Connection 221 Setup procedure. 222 """ 223 224 return "OK" 225 226 @assert_description 227 def TSC_iut_disable_audio(self, test: str, pts_addr: bytes, **kwargs): 228 """ 229 Click Ok, then close the audio connection (SCO) between the 230 Implementation Under Test (IUT) and the PTS. Do not close the serivice 231 level connection (SLC) or power-off the IUT. 232 """ 233 234 def disable_audio(): 235 time.sleep(2) 236 if "HFP/HF" in test: 237 self.hfp.DisconnectToAudioAsHandsfree(connection=self.connection) 238 else: 239 self.hfp.SetAudioPath(audio_path=AUDIO_PATH_SPEAKERS) 240 241 threading.Thread(target=disable_audio).start() 242 243 return "OK" 244 245 @assert_description 246 def TSC_verify_no_audio(self, **kwargs): 247 """ 248 Verify the absence of an audio connection (SCO), then click Ok. 249 """ 250 251 return "OK" 252 253 @assert_description 254 def TSC_iut_enable_audio(self, test: str, pts_addr: bytes, **kwargs): 255 """ 256 Click Ok, then initiate an audio connection (SCO) from the 257 Implementation Under Test (IUT) to the PTS. 258 """ 259 260 def enable_audio(): 261 time.sleep(2) 262 if "HFP/HF" in test: 263 self.hfp.ConnectToAudioAsHandsfree(connection=self.connection) 264 else: 265 self.hfp.SetAudioPath(audio_path=AUDIO_PATH_HANDSFREE) 266 267 threading.Thread(target=enable_audio).start() 268 269 return "OK" 270 271 @assert_description 272 def TSC_iut_disable_audio_slc_down_ok(self, pts_addr: bytes, **kwargs): 273 """ 274 Click OK, then close the audio connection (SCO) between the 275 Implementation Under Test (IUT) and the PTS. If necessary, it is OK to 276 close the service level connection. Do not power-off the IUT. 277 """ 278 279 def disable_slc(): 280 time.sleep(2) 281 self.hfp.DisableSlc(connection=self.connection) 282 283 threading.Thread(target=disable_slc).start() 284 285 return "OK" 286 287 @assert_description 288 def TSC_ag_iut_call_no_slc(self, **kwargs): 289 """ 290 Place a call from an external line to the Implementation Under Test 291 (IUT). When the call is active, click Ok. 292 """ 293 294 self.modem.call(IXIT_PHONE_NUMBER) 295 time.sleep(5) # there's a delay before Android registers the call 296 self.hfp.AnswerCall() 297 time.sleep(2) 298 299 return "OK" 300 301 @assert_description 302 def TSC_ag_iut_enable_second_call(self, **kwargs): 303 """ 304 Click Ok, then place a second call from an external line to the 305 Implementation Under Test (IUT). Do not answer the call unless prompted 306 to do so. 307 """ 308 309 def enable_second_call(): 310 time.sleep(2) 311 self.modem.call(IXIT_SECOND_PHONE_NUMBER) 312 313 threading.Thread(target=enable_second_call).start() 314 315 return "OK" 316 317 @assert_description 318 def TSC_ag_iut_call_swap(self, **kwargs): 319 """ 320 Click Ok, then place the current call on hold and make the incoming/held 321 call active using the Implementation Under Test (IUT). 322 """ 323 324 self.hfp.SwapActiveCall() 325 326 return "OK" 327 328 @assert_description 329 def TSC_verify_audio_second_call(self, **kwargs): 330 """ 331 Verify the audio is returned to the 2nd call and then click Ok. Resume 332 action may be needed. If the audio is not returned to the 2nd call, 333 click Cancel. 334 """ 335 336 return "OK" 337 338 @assert_description 339 def TSC_ag_iut_disable_call_after_verdict(self, **kwargs): 340 """ 341 After the test verdict is given, end all active calls using the 342 external line or the Implementation Under Test (IUT). Click OK to 343 continue. 344 """ 345 346 self.hfp.DeclineCall() 347 348 return "OK" 349 350 @assert_description 351 def TSC_disable_ag_cellular_network_expect_no_notification(self, **kwargs): 352 """ 353 Disable the control channel, such that the AG is de-registered. Then, 354 click OK. 355 """ 356 357 return "OK" 358 359 @assert_description 360 def TSC_verify_no_ecnr(self, **kwargs): 361 """ 362 Verify that EC and NR functionality is disabled, then click Ok. 363 """ 364 365 return "OK" 366 367 @assert_description 368 def TSC_disable_inband_ring(self, **kwargs): 369 """ 370 Click Ok, then disable the in-band ringtone using the Implemenation 371 Under Test (IUT). 372 """ 373 374 self.hfp.SetInBandRingtone(enabled=False) 375 self.host.Reset() 376 377 return "OK" 378 379 @assert_description 380 def TSC_wait_until_ringing(self, **kwargs): 381 """ 382 When the Implementation Under Test (IUT) alerts the incoming call, click 383 Ok. 384 """ 385 386 # we are triggering a call from modem_simulator, so the alert is immediate 387 388 return "OK" 389 390 @assert_description 391 def TSC_verify_incoming_call_ag(self, **kwargs): 392 """ 393 Verify that there is an incoming call on the Implementation Under Test 394 (IUT). 395 """ 396 397 # we are triggering a call from modem_simulator, so this is guaranteed 398 399 return "OK" 400 401 @assert_description 402 def TSC_disable_ag_cellular_network_expect_notification(self, pts_addr: bytes, **kwargs): 403 """ 404 Click OK. Then, disable the control channel, such that the AG is de- 405 registered. 406 """ 407 408 def disable_slc(): 409 time.sleep(2) 410 self.hfp.DisableSlc(connection=self.connection) 411 412 threading.Thread(target=disable_slc).start() 413 414 return "OK" 415 416 @assert_description 417 def TSC_adjust_ag_battery_level_expect_no_notification(self, **kwargs): 418 """ 419 Adjust the battery level on the AG to a level that should cause a 420 battery level indication to be sent to HF. Then, click OK. 421 """ 422 423 self.hfp.SetBatteryLevel(connection=self.connection, battery_percentage=42) 424 425 return "OK" 426 427 def TSC_verify_subscriber_number(self, **kwargs): 428 """ 429 Using the Implementation Under Test (IUT), verify that the following is 430 a valid Audio Gateway (AG) subscriber number, then click 431 Ok."+15551234567"nnNOTE: Subscriber service type is 145 432 """ 433 434 return "OK" 435 436 def TSC_ag_prepare_at_bldn(self, **kwargs): 437 r""" 438 Place the Implemenation Under Test (IUT) in a state which will accept an 439 outgoing call set-up request from the PTS, then click OK. 440 441 Note: The 442 PTS will send a request to establish an outgoing call from the IUT to 443 the last dialed number. Answer the incoming call when alerted. 444 """ 445 446 self.hfp.MakeCall(number=str(IXIT_PHONE_NUMBER)) 447 self.log("Calling") 448 time.sleep(2) 449 self.hfp.DeclineCall() 450 self.log("Declining") 451 time.sleep(2) 452 453 return "OK" 454 455 @assert_description 456 def TSC_ag_iut_prepare_for_atd(self, **kwargs): 457 """ 458 Place the Implementation Under Test (IUT) in a mode that will allow an 459 outgoing call initiated by the PTS, and click Ok. 460 """ 461 462 return "OK" 463 464 @assert_description 465 def TSC_terminal_answer_call(self, **kwargs): 466 """ 467 Click Ok, then answer the incoming call on the external terminal. 468 """ 469 470 def answer_call(): 471 time.sleep(2) 472 self.log("Answering") 473 self.modem.answer_outgoing_call(IXIT_PHONE_NUMBER) 474 475 threading.Thread(target=answer_call).start() 476 477 return "OK" 478 479 @match_description 480 def TSC_signal_strength_verify(self, **kwargs): 481 """ 482 Verify that the signal reported on the Implementaion Under Test \(IUT\) is 483 proportional to the value \(out of 5\), then click Ok.[0-9] 484 """ 485 486 return "OK" 487 488 @assert_description 489 def TSC_signal_strength_impair(self, **kwargs): 490 """ 491 Impair the cellular signal by placing the Implementation Under Test 492 (IUT) under partial RF shielding, then click Ok. 493 """ 494 495 return "OK" 496 497 @assert_description 498 def TSC_verify_network_operator(self, **kwargs): 499 """ 500 Verify the following information matches the network operator reported 501 on the Implementation Under Test (IUT), then click Ok:"Android Virtual " 502 """ 503 504 return "OK" 505 506 @assert_description 507 def TSC_INFO_slc_with_30_seconds_wait(self, **kwargs): 508 """ 509 After clicking the OK button, PTS will connect to the IUT and then be 510 idle for 30 seconds as part of the test procedure. 511 512 Click OK to proceed. 513 """ 514 515 return "OK" 516 517 @assert_description 518 def TSC_ag_iut_disable_call(self, **kwargs): 519 """ 520 Click Ok, then end the call using the Implemention Under Test IUT). 521 """ 522 523 def disable_call(): 524 time.sleep(2) 525 self.hfp.DeclineCall() 526 527 threading.Thread(target=disable_call).start() 528 529 return "OK" 530 531 @match_description 532 def TSC_dtmf_verify(self, **kwargs): 533 """ 534 Verify the DTMF code, then click Ok. . 535 """ 536 537 return "OK" 538 539 @assert_description 540 def TSC_TWC_instructions(self, **kwargs): 541 """ 542 NOTE: The following rules apply for this test case: 543 544 1. 545 TSPX_phone_number - the 1st call 546 2. TSPX_second_phone_number - the 2nd 547 call 548 549 Edits can be made within the IXIT settings for the above phone 550 numbers. 551 """ 552 553 return "OK" 554 555 def TSC_call_swap_and_disable_held_tester(self, **kwargs): 556 """ 557 Set the Implementation Under Test (IUT) in a state that will allow the 558 PTS to initiate a AT+CHLD=1 operation, then click Ok. 559 560 Note: Upon 561 receiving the said command, the IUT will simultaneously drop the active 562 call and make the held call active. 563 """ 564 565 return "OK" 566 567 @assert_description 568 def TSC_verify_audio_first_call(self, **kwargs): 569 """ 570 Verify the audio is returned to the 1st call and click Ok. Resume action 571 my be needed. If the audio is not present in the 1st call, click 572 Cancel. 573 """ 574 575 # TODO 576 577 return "OK" 578 579 @assert_description 580 def TSC_ag_iut_dial_out_second(self, **kwargs): 581 """ 582 Verify that the last number dialed on the Implementation Under Test 583 (IUT) matches the TSPX_Second_phone_number entered in the IXIT settings. 584 """ 585 586 # TODO 587 588 return "OK" 589 590 @assert_description 591 def TSC_prepare_iut_for_vra(self, pts_addr: bytes, test: str, **kwargs): 592 """ 593 Place the Implementation Under Test (IUT) in a state which will allow a 594 request from the PTS to activate voice recognition, then click Ok. 595 """ 596 597 if "HFP/HF" not in test: 598 self.hfp.SetVoiceRecognition( 599 enabled=True, 600 connection=self.connection, 601 ) 602 603 return "OK" 604 605 @assert_description 606 def TSC_prepare_iut_for_vrd(self, **kwargs): 607 """ 608 Place the Implementation Under Test (IUT) in a state which will allow a 609 voice recognition deactivation from PTS, then click Ok. 610 """ 611 612 return "OK" 613 614 @assert_description 615 def TSC_ag_iut_clear_call_history(self, **kwargs): 616 """ 617 Clear the call history on the Implementation Under Test (IUT) such that 618 there are zero records of any numbers dialed, then click Ok. 619 """ 620 621 self.hfp.ClearCallHistory() 622 623 return "OK" 624 625 @assert_description 626 def TSC_reject_call(self, test: str, pts_addr: bytes, **kwargs): 627 """ 628 Click Ok, then reject the incoming call using the Implemention Under 629 Test (IUT). 630 """ 631 632 def reject_call(): 633 time.sleep(2) 634 if "HFP/HF" in test: 635 self.hfp.DeclineCallAsHandsfree(connection=self.connection) 636 else: 637 self.hfp.DeclineCall() 638 639 threading.Thread(target=reject_call).start() 640 641 return "OK" 642 643 @assert_description 644 def TSC_hf_iut_answer_call(self, pts_addr: bytes, **kwargs): 645 """ 646 Click Ok, then answer the incoming call using the Implementation Under 647 Test (IUT). 648 """ 649 650 def answer_call(): 651 time.sleep(2) 652 self.hfp.AnswerCallAsHandsfree(connection=self.connection) 653 654 threading.Thread(target=answer_call).start() 655 656 return "OK" 657 658 @assert_description 659 def TSC_iut_disable_audio_poweroff_ok(self, **kwargs): 660 """ 661 Click Ok, then close the audio connection (SCO) by one of the following 662 ways: 663 664 1. Close the service level connection (SLC) 665 2. Powering off the 666 Implementation Under Test (IUT) 667 """ 668 669 self.host.Reset() 670 671 return "OK" 672 673 @assert_description 674 def TSC_verify_inband_ring(self, **kwargs): 675 """ 676 Verify that the in-band ringtone is audible, then click Ok. 677 """ 678 679 return "OK" 680 681 @assert_description 682 def TSC_verify_inband_ring_muting(self, **kwargs): 683 """ 684 Verify that the in-band ringtone is not audible , then click Ok. 685 """ 686 687 return "OK" 688 689 @assert_description 690 def TSC_hf_iut_disable_call(self, pts_addr: bytes, **kwargs): 691 """ 692 Click Ok, then end the call process from the Implementation Under Test 693 (IUT). 694 """ 695 696 def disable_call(): 697 time.sleep(2) 698 self.hfp.EndCallAsHandsfree(connection=self.connection) 699 700 threading.Thread(target=disable_call).start() 701 702 return "OK" 703 704 @assert_description 705 def TSC_mute_inband_ring_iut(self, **kwargs): 706 """ 707 Mute the in-band ringtone on the Implementation Under Test (IUT) and 708 then click OK. 709 """ 710 711 return "OK" 712 713 @assert_description 714 def TSC_verify_iut_alerting(self, **kwargs): 715 """ 716 Verify that the Implementation Under Test (IUT) is generating a local 717 alert, then click Ok. 718 """ 719 720 return "OK" 721 722 @assert_description 723 def TSC_verify_iut_not_alerting(self, **kwargs): 724 """ 725 Verify that the Implementation Under Test (IUT) is not generating a 726 local alert. 727 """ 728 729 return "OK" 730 731 @assert_description 732 def TSC_hf_iut_enable_call_number(self, pts_addr: bytes, **kwargs): 733 """ 734 Click Ok, then place an outgoing call from the Implementation Under Test 735 (IUT) using an enterted phone number. 736 """ 737 738 def disable_call(): 739 time.sleep(2) 740 self.hfp.MakeCallAsHandsfree(connection=self.connection, number="42") 741 742 threading.Thread(target=disable_call).start() 743 744 return "OK" 745 746 @assert_description 747 def TSC_hf_iut_enable_call_memory(self, **kwargs): 748 """ 749 Click Ok, then place an outgoing call from the Implementation Under Test 750 (IUT) by entering the memory index. For further clarification please 751 see the HFP 1.5 Specification. 752 """ 753 754 def enable_call(): 755 time.sleep(2) 756 self.hfp.MakeCallAsHandsfree(connection=self.connection, number=">1") 757 758 threading.Thread(target=enable_call).start() 759 760 return "OK" 761 762 @assert_description 763 def TSC_hf_iut_call_swap_then_disable_held_alternative(self, pts_addr: bytes, **kwargs): 764 """ 765 Using the Implementation Under Test (IUT), perform one of the following 766 two actions: 767 768 1. Click OK, make the held/waiting call active, disabling 769 the active call. 770 2. Click OK, make the held/waiting call active, placing 771 the active call on hold. 772 """ 773 774 def call_swap_then_disable_held_alternative(): 775 time.sleep(2) 776 self.hfp.CallTransferAsHandsfree(connection=self.connection) 777 778 threading.Thread(target=call_swap_then_disable_held_alternative).start() 779 780 return "OK" 781 782 @assert_description 783 def TSC_iut_make_discoverable(self, **kwargs): 784 """ 785 Place the Implementation Under Test (IUT) in discoverable mode, then 786 click Ok. 787 """ 788 789 self.host.SetDiscoverabilityMode(mode=DISCOVERABLE_GENERAL) 790 791 return "OK" 792 793 @assert_description 794 def TSC_iut_accept_connection(self, **kwargs): 795 """ 796 Click Ok, then accept the pairing and connection requests on the 797 Implementation Under Test (IUT), if prompted. 798 """ 799 800 return "OK" 801 802 @assert_description 803 def TSC_voice_recognition_enable_iut(self, pts_addr: bytes, **kwargs): 804 """ 805 Using the Implementation Under Test (IUT), activate voice recognition. 806 """ 807 808 self.hfp.SetVoiceRecognitionAsHandsfree( 809 enabled=True, 810 connection=self.connection, 811 ) 812 813 return "OK" 814 815 @assert_description 816 def TSC_voice_recognition_disable_iut(self, pts_addr: bytes, **kwargs): 817 """ 818 Using the Implementation Under Test (IUT), deactivate voice recognition. 819 """ 820 821 self.hfp.SetVoiceRecognitionAsHandsfree( 822 enabled=False, 823 connection=self.connection, 824 ) 825 826 return "OK" 827 828 @match_description 829 def TSC_dtmf_send(self, pts_addr: bytes, dtmf: str, **kwargs): 830 r""" 831 Send the DTMF code, then click Ok. (?P<dtmf>.*) 832 """ 833 834 self.hfp.SendDtmfFromHandsfree( 835 connection=self.connection, 836 code=dtmf[0].encode("ascii")[0], 837 ) 838 839 return "OK" 840 841 @assert_description 842 def TSC_verify_hf_iut_reports_held_and_active_call(self, **kwargs): 843 """ 844 Verify that the Implementation Under Test (IUT) interprets both held and 845 active call signals, then click Ok. If applicable, verify that the 846 information is correctly displayed on the IUT, then click Ok. 847 """ 848 849 return "OK" 850 851 def TSC_rf_shield_iut_or_pts(self, **kwargs): 852 """ 853 Click Ok, then move the PTS and the Implementation Under Test (IUT) out 854 of range of each other by performing one of the following IUT specific 855 actions: 856 857 1. Hands Free (HF) IUT - Place the IUT in the RF shield box or 858 physically take out of range from the PTS. 859 860 2. Audio Gateway (AG) IUT- 861 Physically take the IUT out range. Do not place in the RF shield box as 862 it will interfere with the cellular network. 863 864 Note: The PTS can also be 865 placed in the RF shield box if necessary. 866 """ 867 868 def shield_iut_or_pts(): 869 time.sleep(2) 870 self.rootcanal.move_out_of_range() 871 872 threading.Thread(target=shield_iut_or_pts).start() 873 874 return "OK" 875 876 @assert_description 877 def TSC_rf_shield_open(self, **kwargs): 878 """ 879 Click Ok, then remove the Implementation Under Test (IUT) and/or the PTS 880 from the RF shield. If the out of range method was used, bring the IUT 881 and PTS back within range. 882 """ 883 884 def shield_open(): 885 time.sleep(2) 886 self.rootcanal.move_in_range() 887 888 threading.Thread(target=shield_open).start() 889 890 return "OK" 891 892 @match_description 893 def TSC_verify_speaker_volume(self, volume: str, **kwargs): 894 r""" 895 Verify that the Hands Free \(HF\) speaker volume is displayed correctly on 896 the Implementation Under Test \(IUT\).(?P<volume>[0-9]*) 897 """ 898 899 return "OK" 900 901 @assert_description 902 def TSC_ag_iut_clear_memory(self, **kwargs): 903 """ 904 Clear the memory indexed by TSPX_phone_number_memory on the AG such that 905 the memory slot becomes empty, then Click OK. 906 """ 907 self.hfp.ClearCallHistory() 908 909 return "OK" 910 911 @assert_description 912 def TSC_enable_call_memory_invalid_tester(self, **kwargs): 913 """ 914 The PTS will send a call request containing an invalid/out of range 915 memory index from the TSPX_phone_number_memory_invalid_index found in 916 the IXIT settings. 917 """ 918 919 return "OK" 920 921 @assert_description 922 def TSC_hf_iut_enable_call_memory_invalid(self, pts_addr: bytes, **kwargs): 923 """ 924 Click Ok, then attempt to place an outgoing call from the Implementation 925 Under Test (IUT) by entering a memory index which does not equal the 926 TSPX_phone_number_memory. For further clarification please see the HFP 927 1.5 Specification. 928 """ 929 930 def enable_call(): 931 time.sleep(2) 932 self.hfp.MakeCallAsHandsfree(connection=self.connection, number=">9999") 933 934 threading.Thread(target=enable_call).start() 935 936 return "OK" 937 938 @assert_description 939 def TSC_hf_iut_verify_call_disable(self, **kwargs): 940 """ 941 Verify that the call is disabled on the Implementation Under Test (IUT) 942 and then click Ok. 943 """ 944 945 return "OK" 946 947 @assert_description 948 def TSC_verify_subscriber_number_unsupported(self, **kwargs): 949 """ 950 Using the Implementation Under Test (IUT), verify that the subscriber 951 number information is not supported by the PTS, then click Ok. 952 """ 953 954 return "OK" 955 956 @assert_description 957 def TSC_query_call_list(self, **kwargs): 958 """ 959 Using the Implementation Under Test (IUT), query the list of currents 960 calls on the Audio Gateway (AG), then click Ok. 961 """ 962 963 return "OK" 964 965 @assert_description 966 def TSC_verify_clcc_receipt(self, **kwargs): 967 """ 968 Verify that the +CLCC response(s) received by the Implementation Under 969 Test (IUT) contains the correct call status information, then click Ok. 970 """ 971 972 return "OK" 973 974 @assert_description 975 def TSC_impair_ag_signal_expect_no_notification(self, **kwargs): 976 """ 977 Impair the signal to the AG so that a reduction in signal strength can 978 be observed. Then, click OK. 979 """ 980 981 return "OK" 982 983 @assert_description 984 def TSC_hf_iut_enable_call_last(self, pts_addr: bytes, **kwargs): 985 """ 986 Click Ok, then place an outgoing call to the last number dialed on the 987 Implementation Under Test (IUT). 988 """ 989 990 def enable_call(): 991 time.sleep(2) 992 self.hfp.MakeCallAsHandsfree(connection=self.connection, number="123") 993 994 threading.Thread(target=enable_call).start() 995 996 return "OK" 997 998 @assert_description 999 def TSC_hf_disable_ecnr(self, **kwargs): 1000 """ 1001 Using the Implemenation Under Test (IUT), disable EC/NR, then click Ok. 1002 """ 1003 1004 return "OK" 1005 1006 @assert_description 1007 def TSC_ag_iut_answer_call(self, **kwargs): 1008 """ 1009 Click Ok, then answer the incoming call on the Implementation Under Test 1010 (IUT). 1011 """ 1012 1013 self.hfp.AnswerCall() 1014 1015 return "OK" 1016 1017 @assert_description 1018 def TSC_verify_iut_ignore_wrong_bind(self, **kwargs): 1019 """ 1020 Verify IUT ignores unkown or unexpected indication code. Then click OK. 1021 """ 1022 1023 return "OK" 1024 1025 def _auto_confirm_requests(self, times=None): 1026 1027 def task(): 1028 cnt = 0 1029 pairing_events = self.security.OnPairing() 1030 for event in pairing_events: 1031 if event.WhichOneof("method") in {"just_works", "numeric_comparison"}: 1032 if times is None or cnt < times: 1033 cnt += 1 1034 pairing_events.send(PairingEventAnswer(event=event, confirm=True)) 1035 1036 threading.Thread(target=task).start() 1037