1 #/usr/bin/env python3.4 2 # 3 # Copyright (C) 2016 The Android Open Source Project 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 # use this file except in compliance with the License. You may obtain a copy of 7 # 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, WITHOUT 13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 # License for the specific language governing permissions and limitations under 15 # the License. 16 """ 17 Test the HFP profile for conference calling functionality. 18 """ 19 20 import time 21 22 from acts.test_decorators import test_tracker_info 23 from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest 24 from acts.test_utils.bt.BluetoothCarHfpBaseTest import BluetoothCarHfpBaseTest 25 from acts.test_utils.bt import BtEnum 26 from acts.test_utils.bt import bt_test_utils 27 from acts.test_utils.car import car_telecom_utils 28 from acts.test_utils.tel import tel_defines 29 from acts.test_utils.tel.tel_test_utils import hangup_call 30 from acts.test_utils.tel.tel_test_utils import initiate_call 31 from acts.test_utils.tel.tel_test_utils import wait_and_answer_call 32 from acts.test_utils.tel.tel_test_utils import wait_for_ringing_call 33 from acts.test_utils.tel.tel_voice_utils import get_audio_route 34 from acts.test_utils.tel.tel_voice_utils import set_audio_route 35 from acts.test_utils.tel.tel_voice_utils import swap_calls 36 37 BLUETOOTH_PKG_NAME = "com.android.bluetooth" 38 CALL_TYPE_OUTGOING = "CALL_TYPE_OUTGOING" 39 CALL_TYPE_INCOMING = "CALL_TYPE_INCOMING" 40 SHORT_TIMEOUT = 3 41 42 43 class BtCarHfpConferenceTest(BluetoothCarHfpBaseTest): 44 def setup_class(self): 45 if not super(BtCarHfpConferenceTest, self).setup_class(): 46 return False 47 48 # Connect the devices now, try twice. 49 attempts = 2 50 connected = False 51 while attempts > 0 and not connected: 52 connected = bt_test_utils.connect_pri_to_sec( 53 self.hf, self.ag, 54 set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])) 55 self.log.info("Connected {}".format(connected)) 56 attempts -= 1 57 return connected 58 59 @test_tracker_info(uuid='a9657693-b534-4625-bf91-69a1d1b9a943') 60 @BluetoothBaseTest.bt_test_wrap 61 def test_multi_way_call_accept(self): 62 """ 63 Tests if we can have a 3-way calling between re, RE2 and AG/HF. 64 65 Precondition: 66 1. Devices are connected over HFP. 67 68 Steps: 69 1. Make a call from re to AG 70 2. Wait for dialing on re and ringing on HF/AG. 71 3. Accept the call on HF 72 4. Make a call on RE2 to AG 73 5. Wait for dialing on re and ringing on HF/AG. 74 6. Accept the call on HF. 75 7. See that HF/AG have one active and one held call. 76 8. Merge the call on HF. 77 9. Verify that we have a conference call on HF/AG. 78 10. Hangup the call on HF. 79 11. Wait for all devices to go back into stable state. 80 81 Returns: 82 Pass if True 83 Fail if False 84 85 Priority: 0 86 """ 87 timeout_for_state_updates = 3 88 # Dial AG from re 89 if not initiate_call(self.log, self.re, self.ag_phone_number): 90 self.log.error("Failed to initiate call from re.") 91 return False 92 93 # Wait for dialing/ringing 94 ret = True 95 ret &= wait_for_ringing_call(self.log, self.ag) 96 ret &= car_telecom_utils.wait_for_ringing(self.log, self.hf) 97 98 if not ret: 99 self.log.error("Failed to dial incoming number from") 100 return False 101 102 # Give time for state to update due to carrier limitations 103 time.sleep(SHORT_TIMEOUT) 104 # Extract the call. 105 call_1 = car_telecom_utils.get_calls_in_states( 106 self.log, self.hf, [tel_defines.CALL_STATE_RINGING]) 107 if len(call_1) != 1: 108 self.hf.log.error("Call State in ringing failed {}".format(call_1)) 109 return False 110 111 # Accept the call on HF 112 if not car_telecom_utils.accept_call(self.log, self.hf, call_1[0]): 113 self.hf.log.error("Accepting call failed {}".format( 114 self.hf.serial)) 115 return False 116 117 # Dial another call from RE2 118 if not initiate_call(self.log, self.re2, self.ag_phone_number): 119 self.re2.log.error("Failed to initiate call from re.") 120 return False 121 122 # Wait for dialing/ringing 123 ret &= wait_for_ringing_call(self.log, self.ag) 124 ret &= car_telecom_utils.wait_for_ringing(self.log, self.hf) 125 126 if not ret: 127 self.log.error("AG and HF not in ringing state.") 128 return False 129 130 # Give time for state to update due to carrier limitations 131 time.sleep(SHORT_TIMEOUT) 132 # Extract the call. 133 #input("Continue?") 134 call_2 = car_telecom_utils.get_calls_in_states( 135 self.log, self.hf, [tel_defines.CALL_STATE_RINGING]) 136 if len(call_2) != 1: 137 self.hf.log.info("Call State in ringing failed {}".format(call_2)) 138 return False 139 140 # Accept the call on HF 141 if not car_telecom_utils.accept_call(self.log, self.hf, call_2[0]): 142 self.hf.log.info("Accepting call failed {}".format( 143 calls_in_ringing)) 144 return False 145 146 # Merge the calls now. 147 self.hf.droid.telecomCallJoinCallsInConf(call_1[0], call_2[0]) 148 149 # Check if we are in conference with call_1 and call_2 150 conf_call_id = car_telecom_utils.wait_for_conference( 151 self.log, self.hf, [call_1[0], call_2[0]]) 152 if conf_call_id == None: 153 self.hf.log.error("Did not get the conference setup correctly") 154 return False 155 156 # Now hangup the conference call. 157 if not car_telecom_utils.hangup_conf(self.log, self.hf, conf_call_id): 158 self.hf.log.error("Could not hangup conference call {}!".format( 159 conf_call_id)) 160 return False 161 162 return True 163