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 basic calling functionality. 18 """ 19 20 import time 21 from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest 22 from acts.test_utils.bt.BluetoothCarHfpBaseTest import BluetoothCarHfpBaseTest 23 from acts.test_utils.bt import BtEnum 24 from acts.test_utils.bt import bt_test_utils 25 from acts.test_utils.car import car_telecom_utils 26 from acts.test_utils.car import tel_telecom_utils 27 from acts.test_utils.tel import tel_defines 28 29 BLUETOOTH_PKG_NAME = "com.android.bluetooth" 30 CALL_TYPE_OUTGOING = "CALL_TYPE_OUTGOING" 31 CALL_TYPE_INCOMING = "CALL_TYPE_INCOMING" 32 SHORT_TIMEOUT = 5 33 34 35 class BtCarHfpTest(BluetoothCarHfpBaseTest): 36 def setup_class(self): 37 if not super(BtCarHfpTest, self).setup_class(): 38 return False 39 # Disable the A2DP profile. 40 bt_test_utils.set_profile_priority( 41 self.hf, self.ag, [BtEnum.BluetoothProfile.PBAP_CLIENT.value, 42 BtEnum.BluetoothProfile.A2DP_SINK.value], 43 BtEnum.BluetoothPriorityLevel.PRIORITY_OFF) 44 bt_test_utils.set_profile_priority( 45 self.hf, self.ag, [BtEnum.BluetoothProfile.HEADSET_CLIENT.value], 46 BtEnum.BluetoothPriorityLevel.PRIORITY_ON) 47 48 if not bt_test_utils.connect_pri_to_sec(self.hf, self.ag, set( 49 [BtEnum.BluetoothProfile.HEADSET_CLIENT.value])): 50 self.log.error("Failed to connect.") 51 return False 52 return True 53 54 #@BluetoothTest(UUID=4ce2195a-b70a-4584-912e-cbd20d20e19d) 55 @BluetoothBaseTest.bt_test_wrap 56 def test_default_calling_account(self): 57 """ 58 Tests if the default calling account is coming from the 59 bluetooth pacakge. 60 61 Precondition: 62 1. Devices are connected. 63 64 Steps: 65 1. Check if the default calling account is via Bluetooth package. 66 67 Returns: 68 Pass if True 69 Fail if False 70 71 Priority: 0 72 """ 73 selected_acc = \ 74 self.hf.droid.telecomGetUserSelectedOutgoingPhoneAccount() 75 if not selected_acc: 76 self.hf.log.error("No default account found.") 77 return False 78 79 # Check if the default account is from the Bluetooth package. This is a 80 # light weight check. 81 try: 82 acc_component_id = selected_acc['ComponentName'] 83 except KeyError: 84 self.hf.log.error("No component name for account {}".format( 85 selected_acc)) 86 return False 87 if not acc_component_id.startswith(BLUETOOTH_PKG_NAME): 88 self.hf.log.error("Component name does not start with pkg name {}". 89 format(selected_acc)) 90 return False 91 return True 92 93 #@BluetoothTest(UUID=e579009d-05f3-4236-a698-5de8c11d73a9) 94 @BluetoothBaseTest.bt_test_wrap 95 def test_outgoing_call_hf(self): 96 """ 97 Tests if we can make a phone call from HF role and disconnect from HF 98 role. 99 100 Precondition: 101 1. Devices are connected. 102 103 Steps: 104 1. Make a call from HF role. 105 2. Wait for the HF, AG to be dialing and RE to see the call ringing. 106 3. Hangup the call on HF role. 107 4. Wait for all devices to hangup the call. 108 109 Returns: 110 Pass if True 111 Fail if False 112 113 Priority: 0 114 """ 115 return self.dial_a_hangup_b(self.hf, self.hf) 116 117 #@BluetoothTest(UUID=c9d5f9cd-f275-4adf-b212-c2e9a70d4cac) 118 @BluetoothBaseTest.bt_test_wrap 119 def test_outgoing_call_ag(self): 120 """ 121 Tests if we can make a phone call from AG role and disconnect from AG 122 role. 123 124 Precondition: 125 1. Devices are connected. 126 127 Steps: 128 1. Make a call from AG role. 129 2. Wait for the HF, AG to be in dialing and RE to see the call ringing. 130 3. Hangup the call on AG role. 131 4. Wait for all devices to hangup the call. 132 133 Returns: 134 Pass if True 135 Fail if False 136 137 Priority: 0 138 """ 139 return self.dial_a_hangup_b(self.ag, self.ag) 140 141 #@BluetoothTest(UUID=908c199b-ca65-4694-821d-1b864ee3fe69) 142 @BluetoothBaseTest.bt_test_wrap 143 def test_outgoing_dial_ag_hangup_hf(self): 144 """ 145 Tests if we can make a phone call from AG role and disconnect from HF 146 role. 147 148 Precondition: 149 1. Devices are connected. 150 151 Steps: 152 1. Make a call from AG role. 153 2. Wait for the HF, AG to show dialing and RE to see the call ringing. 154 3. Hangup the call on HF role. 155 4. Wait for all devices to hangup the call. 156 157 Returns: 158 Pass if True 159 Fail if False 160 161 Priority: 0 162 """ 163 return self.dial_a_hangup_b(self.ag, self.hf) 164 165 #@BluetoothTest(UUID=5d1d52c7-51d8-4c82-b437-2e91a6220db3) 166 @BluetoothBaseTest.bt_test_wrap 167 def test_outgoing_dial_hf_hangup_ag(self): 168 """ 169 Tests if we can make a phone call from HF role and disconnect from AG 170 role. 171 172 Precondition: 173 1. Devices are connected. 174 175 Steps: 176 1. Make a call from HF role. 177 2. Wait for the HF, AG to show dialing and RE to see the call ringing. 178 3. Hangup the call on AG role. 179 4. Wait for all devices to hangup the call. 180 181 Returns: 182 Pass if True 183 Fail if False 184 185 Priority: 0 186 """ 187 return self.dial_a_hangup_b(self.hf, self.ag) 188 189 #@BluetoothTest(UUID=a718e238-7e31-40c9-a45b-72081210cc73) 190 @BluetoothBaseTest.bt_test_wrap 191 def test_incoming_dial_re_hangup_re(self): 192 """ 193 Tests if we can make a phone call from remote and disconnect from 194 remote. 195 196 Precondition: 197 1. Devices are connected. 198 199 Steps: 200 1. Make a call from RE role. 201 2. Wait for the HF, AG to show ringing and RE to see the call dialing. 202 3. Hangup the call on RE role. 203 4. Wait for all devices to hangup the call. 204 205 Returns: 206 Pass if True 207 Fail if False 208 209 Priority: 0 210 """ 211 return self.dial_a_hangup_b(self.re, self.re, self.ag_phone_number) 212 213 def dial_a_hangup_b(self, caller, callee, ph=""): 214 """ 215 a, b and c can be either of AG, HF or Remote. 216 1. Make a call from 'a' on a fixed number. 217 2. Wait for the call to get connected (check on both 'a' and 'b') 218 Check that 'c' is in ringing state. 219 3. Hangup the call on 'b'. 220 4. Wait for call to get completely disconnected 221 (check on both 'a' and 'b') 222 It is assumed that scenarios will not go into voice mail. 223 """ 224 if ph == "": ph = self.re_phone_number 225 226 # Determine if this is outgoing or incoming call. 227 call_type = None 228 if caller == self.ag or caller == self.hf: 229 call_type = CALL_TYPE_OUTGOING 230 if callee != self.ag and callee != self.hf: 231 self.log.info("outgoing call should terminate at AG or HF") 232 return False 233 elif caller == self.re: 234 call_type = CALL_TYPE_INCOMING 235 if callee != self.re: 236 self.log.info("Incoming call should terminate at Re") 237 return False 238 239 self.log.info("Call type is {}".format(call_type)) 240 241 # make a call on 'caller' 242 if not tel_telecom_utils.dial_number(self.log, caller, ph): 243 return False 244 245 # Give time for state to update due to carrier limitations 246 time.sleep(SHORT_TIMEOUT) 247 # Check that everyone is in dialing/ringing state. 248 ret = True 249 if call_type == CALL_TYPE_OUTGOING: 250 ret &= tel_telecom_utils.wait_for_dialing(self.log, self.hf) 251 ret &= tel_telecom_utils.wait_for_dialing(self.log, self.ag) 252 ret &= tel_telecom_utils.wait_for_ringing(self.log, self.re) 253 else: 254 ret &= tel_telecom_utils.wait_for_ringing(self.log, self.hf) 255 ret &= tel_telecom_utils.wait_for_ringing(self.log, self.ag) 256 ret &= tel_telecom_utils.wait_for_dialing(self.log, self.re) 257 if not ret: 258 return False 259 260 # Give time for state to update due to carrier limitations 261 time.sleep(SHORT_TIMEOUT) 262 # Check if we have any calls with dialing or active state on 'b'. 263 # We assume we never disconnect from 'ringing' state since it will lead 264 # to voicemail. 265 call_state_dialing_or_active = \ 266 [tel_defines.CALL_STATE_CONNECTING, 267 tel_defines.CALL_STATE_DIALING, 268 tel_defines.CALL_STATE_ACTIVE] 269 270 calls_in_dialing_or_active = tel_telecom_utils.get_calls_in_states( 271 self.log, callee, call_state_dialing_or_active) 272 273 # Make sure there is only one! 274 if len(calls_in_dialing_or_active) != 1: 275 self.log.info("Call State in dialing or active failed {}".format( 276 calls_in_dialing_or_active)) 277 return False 278 279 # Hangup the *only* call on 'callee' 280 if not car_telecom_utils.hangup_call(self.log, callee, 281 calls_in_dialing_or_active[0]): 282 return False 283 284 time.sleep(SHORT_TIMEOUT) 285 # Make sure everyone got out of in call state. 286 for d in self.android_devices: 287 ret &= tel_telecom_utils.wait_for_not_in_call(self.log, d) 288 return ret 289