blob: 2806feb44e31443eba595dc2252abb24fcd516e1 [file] [log] [blame]
Mark De Ruyterd9c540a2018-05-04 11:21:55 -07001#!/usr/bin/env python3
Sanket Agarwald09c7d82016-05-17 20:24:51 -07002#
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.
Sanket Agarwald09c7d82016-05-17 20:24:51 -070016"""
17Test the HFP profile for basic calling functionality.
18"""
19
20import time
tturneyb72742f2017-08-29 17:46:50 -070021from acts.test_decorators import test_tracker_info
Xianyuan Jia63751fb2020-11-17 00:07:40 +000022from acts_contrib.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
23from acts_contrib.test_utils.bt.BluetoothCarHfpBaseTest import BluetoothCarHfpBaseTest
24from acts_contrib.test_utils.bt import BtEnum
25from acts_contrib.test_utils.bt import bt_test_utils
26from acts_contrib.test_utils.car import car_telecom_utils
27from acts_contrib.test_utils.car import tel_telecom_utils
28from acts_contrib.test_utils.tel import tel_defines
Sanket Agarwald09c7d82016-05-17 20:24:51 -070029
30BLUETOOTH_PKG_NAME = "com.android.bluetooth"
31CALL_TYPE_OUTGOING = "CALL_TYPE_OUTGOING"
32CALL_TYPE_INCOMING = "CALL_TYPE_INCOMING"
Joseph Pirozzo534feea2017-10-19 11:32:45 -070033AUDIO_STATE_DISCONNECTED = 0
34AUDIO_STATE_ROUTED = 2
tturneye3934a22016-10-20 15:47:34 -070035SHORT_TIMEOUT = 5
Sanket Agarwald09c7d82016-05-17 20:24:51 -070036
Sanket Agarwal54ad6232016-05-17 20:24:51 -070037
tturneye3934a22016-10-20 15:47:34 -070038class BtCarHfpTest(BluetoothCarHfpBaseTest):
Sanket Agarwald09c7d82016-05-17 20:24:51 -070039 def setup_class(self):
tturneye3934a22016-10-20 15:47:34 -070040 if not super(BtCarHfpTest, self).setup_class():
Sanket Agarwal54ad6232016-05-17 20:24:51 -070041 return False
Sanket Agarwalbd9689b2016-08-24 11:14:53 -070042 # Disable the A2DP profile.
tturneyb72742f2017-08-29 17:46:50 -070043 bt_test_utils.set_profile_priority(self.hf, self.ag, [
44 BtEnum.BluetoothProfile.PBAP_CLIENT.value,
45 BtEnum.BluetoothProfile.A2DP_SINK.value
46 ], BtEnum.BluetoothPriorityLevel.PRIORITY_OFF)
tturneye3934a22016-10-20 15:47:34 -070047 bt_test_utils.set_profile_priority(
48 self.hf, self.ag, [BtEnum.BluetoothProfile.HEADSET_CLIENT.value],
49 BtEnum.BluetoothPriorityLevel.PRIORITY_ON)
Sanket Agarwalbd9689b2016-08-24 11:14:53 -070050
tturneyb72742f2017-08-29 17:46:50 -070051 if not bt_test_utils.connect_pri_to_sec(
52 self.hf, self.ag,
53 set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value])):
tturney34ee54d2016-11-16 15:29:02 -080054 self.log.error("Failed to connect.")
tturney46060782016-11-14 16:44:38 -080055 return False
tturneye3934a22016-10-20 15:47:34 -070056 return True
Sanket Agarwalbd9689b2016-08-24 11:14:53 -070057
tturneyb72742f2017-08-29 17:46:50 -070058 @test_tracker_info(uuid='4ce2195a-b70a-4584-912e-cbd20d20e19d')
Sanket Agarwald09c7d82016-05-17 20:24:51 -070059 @BluetoothBaseTest.bt_test_wrap
60 def test_default_calling_account(self):
61 """
62 Tests if the default calling account is coming from the
63 bluetooth pacakge.
64
65 Precondition:
66 1. Devices are connected.
67
68 Steps:
69 1. Check if the default calling account is via Bluetooth package.
70
71 Returns:
72 Pass if True
73 Fail if False
74
75 Priority: 0
76 """
77 selected_acc = \
78 self.hf.droid.telecomGetUserSelectedOutgoingPhoneAccount()
79 if not selected_acc:
tturney34ee54d2016-11-16 15:29:02 -080080 self.hf.log.error("No default account found.")
Sanket Agarwald09c7d82016-05-17 20:24:51 -070081 return False
82
83 # Check if the default account is from the Bluetooth package. This is a
84 # light weight check.
85 try:
86 acc_component_id = selected_acc['ComponentName']
87 except KeyError:
tturney34ee54d2016-11-16 15:29:02 -080088 self.hf.log.error("No component name for account {}".format(
Sanket Agarwal54ad6232016-05-17 20:24:51 -070089 selected_acc))
Sanket Agarwald09c7d82016-05-17 20:24:51 -070090 return False
91 if not acc_component_id.startswith(BLUETOOTH_PKG_NAME):
tturney34ee54d2016-11-16 15:29:02 -080092 self.hf.log.error("Component name does not start with pkg name {}".
tturneyb72742f2017-08-29 17:46:50 -070093 format(selected_acc))
Sanket Agarwald09c7d82016-05-17 20:24:51 -070094 return False
tturneye3934a22016-10-20 15:47:34 -070095 return True
Sanket Agarwald09c7d82016-05-17 20:24:51 -070096
tturneyb72742f2017-08-29 17:46:50 -070097 @test_tracker_info(uuid='e579009d-05f3-4236-a698-5de8c11d73a9')
Sanket Agarwald09c7d82016-05-17 20:24:51 -070098 @BluetoothBaseTest.bt_test_wrap
99 def test_outgoing_call_hf(self):
100 """
101 Tests if we can make a phone call from HF role and disconnect from HF
102 role.
103
104 Precondition:
105 1. Devices are connected.
106
107 Steps:
108 1. Make a call from HF role.
109 2. Wait for the HF, AG to be dialing and RE to see the call ringing.
110 3. Hangup the call on HF role.
111 4. Wait for all devices to hangup the call.
112
113 Returns:
114 Pass if True
115 Fail if False
116
117 Priority: 0
118 """
119 return self.dial_a_hangup_b(self.hf, self.hf)
120
tturneyb72742f2017-08-29 17:46:50 -0700121 @test_tracker_info(uuid='c9d5f9cd-f275-4adf-b212-c2e9a70d4cac')
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700122 @BluetoothBaseTest.bt_test_wrap
123 def test_outgoing_call_ag(self):
124 """
125 Tests if we can make a phone call from AG role and disconnect from AG
126 role.
127
128 Precondition:
129 1. Devices are connected.
130
131 Steps:
132 1. Make a call from AG role.
133 2. Wait for the HF, AG to be in dialing and RE to see the call ringing.
134 3. Hangup the call on AG role.
135 4. Wait for all devices to hangup the call.
136
137 Returns:
138 Pass if True
139 Fail if False
140
141 Priority: 0
142 """
143 return self.dial_a_hangup_b(self.ag, self.ag)
144
tturneyb72742f2017-08-29 17:46:50 -0700145 @test_tracker_info(uuid='908c199b-ca65-4694-821d-1b864ee3fe69')
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700146 @BluetoothBaseTest.bt_test_wrap
147 def test_outgoing_dial_ag_hangup_hf(self):
148 """
149 Tests if we can make a phone call from AG role and disconnect from HF
150 role.
151
152 Precondition:
153 1. Devices are connected.
154
155 Steps:
156 1. Make a call from AG role.
157 2. Wait for the HF, AG to show dialing and RE to see the call ringing.
158 3. Hangup the call on HF role.
159 4. Wait for all devices to hangup the call.
160
161 Returns:
162 Pass if True
163 Fail if False
164
165 Priority: 0
166 """
167 return self.dial_a_hangup_b(self.ag, self.hf)
168
tturneyb72742f2017-08-29 17:46:50 -0700169 @test_tracker_info(uuid='5d1d52c7-51d8-4c82-b437-2e91a6220db3')
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700170 @BluetoothBaseTest.bt_test_wrap
171 def test_outgoing_dial_hf_hangup_ag(self):
172 """
173 Tests if we can make a phone call from HF role and disconnect from AG
174 role.
175
176 Precondition:
177 1. Devices are connected.
178
179 Steps:
180 1. Make a call from HF role.
181 2. Wait for the HF, AG to show dialing and RE to see the call ringing.
182 3. Hangup the call on AG role.
183 4. Wait for all devices to hangup the call.
184
185 Returns:
186 Pass if True
187 Fail if False
188
189 Priority: 0
190 """
191 return self.dial_a_hangup_b(self.hf, self.ag)
192
tturneyb72742f2017-08-29 17:46:50 -0700193 @test_tracker_info(uuid='a718e238-7e31-40c9-a45b-72081210cc73')
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700194 @BluetoothBaseTest.bt_test_wrap
195 def test_incoming_dial_re_hangup_re(self):
196 """
197 Tests if we can make a phone call from remote and disconnect from
198 remote.
199
200 Precondition:
201 1. Devices are connected.
202
203 Steps:
204 1. Make a call from RE role.
205 2. Wait for the HF, AG to show ringing and RE to see the call dialing.
206 3. Hangup the call on RE role.
207 4. Wait for all devices to hangup the call.
208
209 Returns:
210 Pass if True
211 Fail if False
212
213 Priority: 0
214 """
215 return self.dial_a_hangup_b(self.re, self.re, self.ag_phone_number)
216
Joseph Pirozzo534feea2017-10-19 11:32:45 -0700217 def test_bluetooth_voice_recognition_assistant(self):
218 """
219 Tests if we can initate a remote Voice Recognition session.
220
221 Precondition:
222 1. Devices are connected.
223
224 Steps:
225 1. Verify that audio isn't routed between the HF and AG.
226 2. From the HF send a BVRA command.
227 3. Verify that audio is routed from the HF to AG.
228 4. From the HF send a BVRA command to stop the session.
229 5. Verify that audio is no longer routed from the HF to AG.
230
231 Returns:
232 Pass if True
233 Fail if False
234
235 Priority: 0
236 """
237 audio_state = self.hf.droid.bluetoothHfpClientGetAudioState(
238 self.ag.droid.bluetoothGetLocalAddress())
239 if (audio_state != AUDIO_STATE_DISCONNECTED):
240 self.log.info(
241 "Audio connected before test started, current state {}.".
242 format(str(audio_state)))
243 return False
244 bvra_started = self.hf.droid.bluetoothHfpClientStartVoiceRecognition(
245 self.ag.droid.bluetoothGetLocalAddress())
246 if (bvra_started != True):
247 self.log.info("BVRA Failed to start.")
248 return False
249 time.sleep(SHORT_TIMEOUT)
250 audio_state = self.hf.droid.bluetoothHfpClientGetAudioState(
251 self.ag.droid.bluetoothGetLocalAddress())
252 if (audio_state != AUDIO_STATE_ROUTED):
253 self.log.info("Audio didn't route, current state {}.".format(
254 str(audio_state)))
255 return False
256 bvra_stopped = self.hf.droid.bluetoothHfpClientStopVoiceRecognition(
257 self.ag.droid.bluetoothGetLocalAddress())
258 if (bvra_stopped != True):
259 self.log.info("BVRA Failed to stop.")
260 return False
261 time.sleep(SHORT_TIMEOUT)
262 audio_state = self.hf.droid.bluetoothHfpClientGetAudioState(
263 self.ag.droid.bluetoothGetLocalAddress())
264 if (audio_state != AUDIO_STATE_DISCONNECTED):
265 self.log.info("Audio didn't cleanup, current state {}.".format(
266 str(audio_state)))
267 return False
268 return True
269
tturneye3934a22016-10-20 15:47:34 -0700270 def dial_a_hangup_b(self, caller, callee, ph=""):
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700271 """
272 a, b and c can be either of AG, HF or Remote.
273 1. Make a call from 'a' on a fixed number.
274 2. Wait for the call to get connected (check on both 'a' and 'b')
275 Check that 'c' is in ringing state.
276 3. Hangup the call on 'b'.
277 4. Wait for call to get completely disconnected
278 (check on both 'a' and 'b')
279 It is assumed that scenarios will not go into voice mail.
280 """
281 if ph == "": ph = self.re_phone_number
282
283 # Determine if this is outgoing or incoming call.
284 call_type = None
tturneye3934a22016-10-20 15:47:34 -0700285 if caller == self.ag or caller == self.hf:
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700286 call_type = CALL_TYPE_OUTGOING
tturneye3934a22016-10-20 15:47:34 -0700287 if callee != self.ag and callee != self.hf:
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700288 self.log.info("outgoing call should terminate at AG or HF")
289 return False
tturneye3934a22016-10-20 15:47:34 -0700290 elif caller == self.re:
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700291 call_type = CALL_TYPE_INCOMING
tturneye3934a22016-10-20 15:47:34 -0700292 if callee != self.re:
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700293 self.log.info("Incoming call should terminate at Re")
294 return False
295
296 self.log.info("Call type is {}".format(call_type))
297
tturney47702802016-11-10 13:56:41 -0800298 # make a call on 'caller'
tturneye3934a22016-10-20 15:47:34 -0700299 if not tel_telecom_utils.dial_number(self.log, caller, ph):
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700300 return False
301
tturneye3934a22016-10-20 15:47:34 -0700302 # Give time for state to update due to carrier limitations
303 time.sleep(SHORT_TIMEOUT)
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700304 # Check that everyone is in dialing/ringing state.
305 ret = True
306 if call_type == CALL_TYPE_OUTGOING:
Sanket Agarwal54ad6232016-05-17 20:24:51 -0700307 ret &= tel_telecom_utils.wait_for_dialing(self.log, self.hf)
308 ret &= tel_telecom_utils.wait_for_dialing(self.log, self.ag)
309 ret &= tel_telecom_utils.wait_for_ringing(self.log, self.re)
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700310 else:
Sanket Agarwal54ad6232016-05-17 20:24:51 -0700311 ret &= tel_telecom_utils.wait_for_ringing(self.log, self.hf)
312 ret &= tel_telecom_utils.wait_for_ringing(self.log, self.ag)
313 ret &= tel_telecom_utils.wait_for_dialing(self.log, self.re)
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700314 if not ret:
315 return False
316
tturneye3934a22016-10-20 15:47:34 -0700317 # Give time for state to update due to carrier limitations
318 time.sleep(SHORT_TIMEOUT)
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700319 # Check if we have any calls with dialing or active state on 'b'.
320 # We assume we never disconnect from 'ringing' state since it will lead
321 # to voicemail.
322 call_state_dialing_or_active = \
323 [tel_defines.CALL_STATE_CONNECTING,
324 tel_defines.CALL_STATE_DIALING,
325 tel_defines.CALL_STATE_ACTIVE]
326
Sanket Agarwal54ad6232016-05-17 20:24:51 -0700327 calls_in_dialing_or_active = tel_telecom_utils.get_calls_in_states(
tturneye3934a22016-10-20 15:47:34 -0700328 self.log, callee, call_state_dialing_or_active)
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700329
330 # Make sure there is only one!
331 if len(calls_in_dialing_or_active) != 1:
332 self.log.info("Call State in dialing or active failed {}".format(
333 calls_in_dialing_or_active))
334 return False
335
tturney47702802016-11-10 13:56:41 -0800336 # Hangup the *only* call on 'callee'
337 if not car_telecom_utils.hangup_call(self.log, callee,
Sanket Agarwal54ad6232016-05-17 20:24:51 -0700338 calls_in_dialing_or_active[0]):
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700339 return False
340
tturney47702802016-11-10 13:56:41 -0800341 time.sleep(SHORT_TIMEOUT)
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700342 # Make sure everyone got out of in call state.
343 for d in self.android_devices:
Sanket Agarwal54ad6232016-05-17 20:24:51 -0700344 ret &= tel_telecom_utils.wait_for_not_in_call(self.log, d)
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700345 return ret