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 advanced functionality and try to create race 18conditions by executing actions quickly. 19""" 20 21import time 22 23from acts.test_decorators import test_tracker_info 24from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest 25from acts.test_utils.bt.BluetoothCarHfpBaseTest import BluetoothCarHfpBaseTest 26from acts.test_utils.bt import BtEnum 27from acts.test_utils.bt import bt_test_utils 28from acts.test_utils.car import car_telecom_utils 29from acts.test_utils.tel import tel_defines 30 31STABILIZATION_DELAY_SEC = 5 32 33 34class BtCarHfpFuzzTest(BluetoothCarHfpBaseTest): 35 def setup_class(self): 36 if not super(BtCarHfpFuzzTest, self).setup_class(): 37 return False 38 39 # Connect the devices now, try twice. 40 attempts = 2 41 connected = False 42 while attempts > 0 and not connected: 43 connected = bt_test_utils.connect_pri_to_sec( 44 self.hf, self.ag, 45 set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])) 46 self.log.info("Connected {}".format(connected)) 47 attempts -= 1 48 49 if not connected: 50 self.log.error("Failed to connect") 51 return False 52 53 # Delay set contains the delay between dial and hangup for a call. 54 # We keep very small delays to significantly large ones to stress test 55 # various kind of timing issues. 56 self.delay_set = [ 57 0.1, 58 0.2, 59 0.3, 60 0.4, 61 0.5, # Very short delays 62 1.0, 63 2.0, 64 3.0, 65 4.0, 66 5.0, # Med delays 67 10.0 68 ] # Large delays 69 70 def dial_a_hangup_b_quick(self, a, b, delay=0, ph=""): 71 """ 72 This test does a quick succession of dial and hangup. We make the test 73 case sleep for delay amount between each dial and hangup. This is 74 different from other test cases where we give enough time for devices 75 to get into a calling state before trying to tear down connection. 76 """ 77 if ph == "": ph = self.re_phone_number 78 79 # Dial from A now. 80 self.log.info("Dialing at droid {}".format(a.droid.getBuildDisplay())) 81 a.droid.telecomCallTelUri(ph) 82 83 # Wait for delay millis. 84 time.sleep(delay) 85 86 # Cancel the call at B. Use end call in this scenario so that we do not 87 # wait for looking up the call! 88 self.log.info("Hanging up at droid {}".format(b.droid.getBuildDisplay( 89 ))) 90 b.droid.telecomEndCall() 91 92 # Check/Wait that we are clear before executing the test. 93 for d in self.android_devices: 94 if not car_telecom_utils.wait_for_not_in_call(self.log, d): 95 self.log.warn( 96 "dial_a_hangup_quick wait_for_not_in_call failed {}". 97 format(d.serial)) 98 return False 99 100 return True 101 102 def stabilize_and_check_sanity(self): 103 # Since we dial and hangup very very quickly we may end up in a state 104 # where we need to wait to see the results. For instance if the delay is 105 # 0.1 sec it may take upto 2 seconds for the platform to respond to a 106 # dial() and hence even if we hangup 0.1 sec later we will not see its 107 # result immidiately (this may be a false positive on test). 108 time.sleep(STABILIZATION_DELAY_SEC) 109 110 # First check if HF is in dialing state, we can send an actual hangup if 111 # that is the case and then wait for devices to come back to normal. 112 if self.hf.droid.telecomIsInCall(): 113 self.log.info("HF still in call, send hangup") 114 self.hf.droid.telecomEndCall() 115 116 # Wait for devices to go back to normal. 117 for d in self.android_devices: 118 if not car_telecom_utils.wait_for_not_in_call(self.log, d): 119 self.log.warning( 120 "stabilize_and_check_sanity wait_for_not_in_call failed {}". 121 format(d.serial)) 122 return False 123 124 return True 125 126 @test_tracker_info(uuid='32022c74-fdf3-44c4-9e82-e518bdcce667') 127 @BluetoothBaseTest.bt_test_wrap 128 def test_fuzz_outgoing_hf(self): 129 """ 130 Test calling and hangup from HF with varied delays as defined in 131 self.delay_set 132 133 Precondition: 134 1. Devices are paired and connected 135 136 Steps: 137 For each delay do the following: 138 a) Call HF 139 b) Wait for delay seconds 140 c) Hangup HF 141 d) Check if all devices are in stable state, if not wait for stabilizing 142 e) If (d) fails then we fail otherwise we go back to (a) 143 f) Once all delays are done we do a final check for sanity as pass 144 scenario 145 146 Returns: 147 Pass if True 148 Fail if False 149 150 Priority: 1 151 """ 152 153 for delay in self.delay_set: 154 self.log.info("test_fuzz outgoing_hf: {}".format(delay)) 155 # Make the call and hangup, we do a light check inside to see if the 156 # phones are in a clean state -- if not, we let them stabilize 157 # before continuing. 158 if not self.dial_a_hangup_b_quick(self.hf, self.hf, delay): 159 if not self.stabilize_and_check_sanity(): 160 self.log.info("Devices not able to stabilize!") 161 return False 162 163 # Final sanity check (if we never called stabilize_and_check_sanity 164 # above). 165 return self.stabilize_and_check_sanity() 166 167 @test_tracker_info(uuid='bc6d52b2-4acc-461e-ad55-fad5a5ecb091') 168 @BluetoothBaseTest.bt_test_wrap 169 def test_fuzz_outgoing_ag(self): 170 """ 171 Test calling and hangup from AG with varied delays as defined in 172 self.delay_set 173 174 Precondition: 175 1. Devices are paired and connected 176 177 Steps: 178 For each delay do the following: 179 a) Call AG 180 b) Wait for delay seconds 181 c) Hangup AG 182 d) Check if all devices are in stable state, if not wait for stabilizing 183 e) If (d) fails then we fail otherwise we go back to (a) 184 f) Once all delays are done we do a final check for sanity as pass 185 scenario 186 187 Returns: 188 Pass if True 189 Fail if False 190 191 Priority: 1 192 """ 193 194 for delay in self.delay_set: 195 self.log.info("test_fuzz outgoing_ag: {}".format(delay)) 196 # Make the call and hangup, we do a light check inside to see if the 197 # phones are in a clean state -- if not, we let them stabilize 198 # before continuing. 199 if not self.dial_a_hangup_b_quick(self.ag, self.ag, delay): 200 if not self.stabilize_and_check_sanity(): 201 self.log.error("Devices not able to stabilize!") 202 return False 203 204 # Final sanity check (if we never called stabilize_and_check_sanity 205 # above). 206 return self.stabilize_and_check_sanity() 207 208 @test_tracker_info(uuid='d834384a-38d5-4260-bfd5-98f8207c04f5') 209 @BluetoothBaseTest.bt_test_wrap 210 def test_fuzz_dial_hf_hangup_ag(self): 211 """ 212 Test calling and hangup from HF and AG resp. with varied delays as defined in 213 self.delay_set 214 215 Precondition: 216 1. Devices are paired and connected 217 218 Steps: 219 For each delay do the following: 220 a) Call HF 221 b) Wait for delay seconds 222 c) Hangup AG 223 d) Check if all devices are in stable state, if not wait for stabilizing 224 e) If (d) fails then we fail otherwise we go back to (a) 225 f) Once all delays are done we do a final check for sanity as pass 226 scenario 227 228 Returns: 229 Pass if True 230 Fail if False 231 232 Priority: 1 233 """ 234 235 for delay in self.delay_set: 236 self.log.info("test_fuzz dial_hf hangup_ag: {}".format(delay)) 237 # Make the call and hangup, we do a light check inside to see if the 238 # phones are in a clean state -- if not, we let them stabilize 239 # before continuing. 240 if not self.dial_a_hangup_b_quick(self.hf, self.ag, delay): 241 if not self.stabilize_and_check_sanity(): 242 self.log.info("Devices not able to stabilize!") 243 return False 244 245 # Final sanity check (if we never called stabilize_and_check_sanity 246 # above). 247 return self.stabilize_and_check_sanity() 248 249 @test_tracker_info(uuid='6de1a8ab-3cb0-4594-a9bb-d882a3414836') 250 @BluetoothBaseTest.bt_test_wrap 251 def test_fuzz_dial_ag_hangup_hf(self): 252 """ 253 Test calling and hangup from HF and AG resp. with varied delays as defined in 254 self.delay_set 255 256 Precondition: 257 1. Devices are paired and connected 258 259 Steps: 260 For each delay do the following: 261 a) Call AG 262 b) Wait for delay seconds 263 c) Hangup HF 264 d) Check if all devices are in stable state, if not wait for stabilizing 265 e) If (d) fails then we fail otherwise we go back to (a) 266 f) Once all delays are done we do a final check for sanity as pass 267 scenario 268 269 Returns: 270 Pass if True 271 Fail if False 272 273 Priority: 1 274 """ 275 276 for delay in self.delay_set: 277 self.log.info("test_fuzz dial_ag hangup_hf: {}".format(delay)) 278 # Make the call and hangup, we do a light check inside to see if the 279 # phones are in a clean state -- if not, we let them stabilize 280 # before continuing. 281 if not self.dial_a_hangup_b_quick(self.ag, self.hf, delay): 282 if not self.stabilize_and_check_sanity(): 283 self.log.info("Devices not able to stabilize!") 284 return False 285 286 # Final sanity check (if we never called stabilize_and_check_sanity 287 # above). 288 return self.stabilize_and_check_sanity() 289