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