1#!/usr/bin/env python3 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""" 17Test the HFP profile for calling and connection management. 18""" 19 20import time 21 22from acts.test_decorators import test_tracker_info 23from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest 24from acts.test_utils.bt.BluetoothCarHfpBaseTest import BluetoothCarHfpBaseTest 25from acts.test_utils.bt import BtEnum 26from acts.test_utils.bt import bt_test_utils 27from acts.test_utils.car import car_bt_utils 28from acts.test_utils.car import car_telecom_utils 29from acts.test_utils.tel import tel_defines 30from acts.test_utils.tel.tel_test_utils import hangup_call 31from acts.test_utils.tel.tel_test_utils import initiate_call 32from acts.test_utils.tel.tel_test_utils import wait_and_answer_call 33 34BLUETOOTH_PKG_NAME = "com.android.bluetooth" 35CALL_TYPE_OUTGOING = "CALL_TYPE_OUTGOING" 36CALL_TYPE_INCOMING = "CALL_TYPE_INCOMING" 37default_timeout = 20 38 39 40class BtCarHfpConnectionTest(BluetoothCarHfpBaseTest): 41 def setup_class(self): 42 if not super(BtCarHfpConnectionTest, self).setup_class(): 43 return False 44 45 # Disable all 46 car_bt_utils.set_car_profile_priorities_off(self.hf, self.ag) 47 48 # Enable A2DP 49 bt_test_utils.set_profile_priority( 50 self.hf, self.ag, [BtEnum.BluetoothProfile.HEADSET_CLIENT], 51 BtEnum.BluetoothPriorityLevel.PRIORITY_ON) 52 53 return True 54 55 def setup_test(self): 56 if not super(BtCarHfpConnectionTest, self).setup_test(): 57 return False 58 self.hf.droid.bluetoothDisconnectConnected( 59 self.ag.droid.bluetoothGetLocalAddress()) 60 61 @test_tracker_info(uuid='a6669f9b-fb49-4bd8-aa9c-9d6369e34442') 62 @BluetoothBaseTest.bt_test_wrap 63 def test_call_transfer_disconnect_connect(self): 64 """ 65 Tests that after we connect when an active call is in progress, 66 we show the call. 67 68 Precondition: 69 1. AG & HF are disconnected but paired. 70 71 Steps: 72 1. Make a call from AG role (since disconnected) 73 2. Accept from RE role and transition the call to Active 74 3. Connect AG & HF 75 4. HF should transition into Active call state. 76 77 Returns: 78 Pass if True 79 Fail if False 80 81 Priority: 1 82 """ 83 # make a call on AG 84 if not initiate_call(self.log, self.ag, self.re_phone_number): 85 self.ag.log.error("Failed to initiate call from ag.") 86 return False 87 if not wait_and_answer_call(self.log, self.re): 88 self.re.log.error("Failed to accept call on re.") 89 return False 90 91 # Wait for AG, RE to go into an Active state. 92 if not car_telecom_utils.wait_for_active(self.log, self.ag): 93 self.ag.log.error("AG not in Active state.") 94 return False 95 if not car_telecom_utils.wait_for_active(self.log, self.re): 96 self.re.log.error("RE not in Active state.") 97 return False 98 99 # Now connect the devices. 100 if not bt_test_utils.connect_pri_to_sec( 101 self.hf, self.ag, 102 set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])): 103 self.log.error("Could not connect HF and AG {} {}".format( 104 self.hf.serial, self.ag.serial)) 105 return False 106 107 # Check that HF is in active state 108 if not car_telecom_utils.wait_for_active(self.log, self.hf): 109 self.hf.log.error("HF not in Active state.") 110 return False 111 112 # Hangup the call and check all devices are clean 113 self.hf.droid.telecomEndCall() 114 ret = True 115 ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.hf) 116 ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.ag) 117 ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.re) 118 119 return ret 120 121 @test_tracker_info(uuid='97727b64-a590-4d84-a257-1facd8aafd16') 122 @BluetoothBaseTest.bt_test_wrap 123 def test_call_transfer_off_on(self): 124 """ 125 Tests that after we turn adapter on when an active call is in 126 progress, we show the call. 127 128 Precondition: 129 1. AG & HF are disconnected but paired. 130 2. HF's adapter is OFF 131 132 Steps: 133 1. Make a call from AG role (since disconnected) 134 2. Accept from RE role and transition the call to Active 135 3. Turn HF's adapter ON 136 4. HF should transition into Active call state. 137 138 Returns: 139 Pass if True 140 Fail if False 141 142 Priority: 1 143 """ 144 # Connect HF & AG 145 if not bt_test_utils.connect_pri_to_sec( 146 self.hf, self.ag, 147 set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])): 148 self.log.error("Could not connect HF and AG {} {}".format( 149 self.hf.serial, self.ag.serial)) 150 return False 151 152 # make a call on AG 153 if not initiate_call(self.log, self.ag, self.re_phone_number): 154 self.ag.log.error("Failed to initiate call from ag.") 155 return False 156 157 # Wait for all HF 158 if not car_telecom_utils.wait_for_dialing(self.log, self.hf): 159 self.hf.log.error("HF not in ringing state.") 160 return False 161 162 # Accept the call on RE 163 if not wait_and_answer_call(self.log, self.re): 164 self.re.log.error("Failed to accept call on re.") 165 return False 166 # Wait for all HF, AG, RE to go into an Active state. 167 if not car_telecom_utils.wait_for_active(self.log, self.hf): 168 self.hf.log.error("HF not in Active state.") 169 return False 170 if not car_telecom_utils.wait_for_active(self.log, self.ag): 171 self.ag.log.error("AG not in Active state.") 172 return False 173 if not car_telecom_utils.wait_for_active(self.log, self.re): 174 self.re.log.error("RE not in Active state.") 175 return False 176 177 # Turn the adapter OFF on HF 178 if not bt_test_utils.disable_bluetooth(self.hf.droid): 179 self.hf.log.error("Failed to turn BT off on HF.") 180 return False 181 182 # Turn adapter ON on HF 183 if not bt_test_utils.enable_bluetooth(self.hf.droid, self.hf.ed): 184 self.hf.log.error("Failed to turn BT ON after call on HF.") 185 return False 186 187 # Check that HF is in active state 188 if not car_telecom_utils.wait_for_active(self.log, self.hf): 189 self.hf.log.error("HF not in Active state.") 190 return False 191 192 # Hangup the call and check all devices are clean 193 self.hf.droid.telecomEndCall() 194 ret = True 195 ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.hf) 196 ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.ag) 197 ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.re) 198 199 return ret 200 201 @test_tracker_info(uuid='95f76e2c-1cdd-4a7c-8e26-863b4c4242be') 202 @BluetoothBaseTest.bt_test_wrap 203 def test_call_transfer_connect_disconnect_connect(self): 204 """ 205 Test that when we go from connect -> disconnect -> connect on an active 206 call then the call is restored on HF. 207 208 Precondition: 209 1. AG & HF are paired 210 211 Steps: 212 0. Connect AG & HF 213 1. Make a call from HF role 214 2. Accept from RE role and transition the call to Active 215 3. Disconnect AG & HF 216 4. Verify that we don't have any calls on HF 217 5. Connect AG & HF 218 6. Verify that HF gets the call back. 219 220 Returns: 221 Pass if True 222 Fail if False 223 224 Priority: 1 225 """ 226 # Now connect the devices. 227 if not bt_test_utils.connect_pri_to_sec( 228 self.hf, self.ag, 229 set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])): 230 self.log.error("Could not connect HF and AG {} {}".format( 231 self.hf.serial, self.ag.serial)) 232 return False 233 234 # make a call on HF 235 if not car_telecom_utils.dial_number(self.log, self.hf, 236 self.re_phone_number): 237 self.hf.log.error("HF not in dialing state.") 238 return False 239 240 # Wait for HF, AG to be dialing and RE to be ringing 241 ret = True 242 ret &= car_telecom_utils.wait_for_dialing(self.log, self.hf) 243 #uncomment once sl4a code has been merged. 244 ret &= car_telecom_utils.wait_for_dialing(self.log, self.ag) 245 ret &= car_telecom_utils.wait_for_ringing(self.log, self.re) 246 247 if not ret: 248 self.log.error("Outgoing call did not get established") 249 return False 250 251 # Accept call on RE. 252 if not wait_and_answer_call(self.log, self.re): 253 self.re.log.error("Failed to accept call on re.") 254 return False 255 256 ret &= car_telecom_utils.wait_for_active(self.log, self.hf) 257 ret &= car_telecom_utils.wait_for_active(self.log, self.ag) 258 ret &= car_telecom_utils.wait_for_active(self.log, self.re) 259 260 if not ret: 261 self.log.error("Outgoing call did not transition to active") 262 return False 263 264 # Disconnect HF & AG 265 self.hf.droid.bluetoothDisconnectConnected( 266 self.ag.droid.bluetoothGetLocalAddress()) 267 268 # We use the proxy of the Call going away as HF disconnected 269 if not car_telecom_utils.wait_for_not_in_call(self.log, self.hf): 270 self.hf.log.error("HF still in call after disconnection.") 271 return False 272 273 # Now connect the devices. 274 if not bt_test_utils.connect_pri_to_sec( 275 self.hf, self.ag, 276 set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])): 277 self.log.error("Could not connect HF and AG {} {}".format( 278 self.hf.serial, self.ag.serial)) 279 # Additional profile connection check for b/ 280 if not bt_test_utils.is_hfp_client_device_connected( 281 self.hf, self.ag.droid.bluetoothGetLocalAddress()): 282 self.hf.log.info( 283 "HFP Client connected even though connection state changed " 284 + " event not found") 285 return False 286 287 # Check that HF is in active state 288 if not car_telecom_utils.wait_for_active(self.log, self.hf): 289 self.hf.log.error("HF not in Active state.") 290 return False 291 292 # Hangup the call and check all devices are clean 293 self.hf.droid.telecomEndCall() 294 ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.hf) 295 ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.ag) 296 ret &= car_telecom_utils.wait_for_not_in_call(self.log, self.re) 297 298 return ret 299