blob: 00fb14decb72793edc91a90c83952e44beeafad9 [file] [log] [blame]
Sanket Agarwald09c7d82016-05-17 20:24:51 -07001#/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"""
18Test the HFP profile for basic calling functionality.
19"""
20
21import time
22
23from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
24from acts.test_utils.bt import BtEnum
25from acts.test_utils.bt import bt_test_utils
26from acts.test_utils.car import car_telecom_utils
27from acts.test_utils.tel import tel_defines
28
29BLUETOOTH_PKG_NAME = "com.android.bluetooth"
30CALL_TYPE_OUTGOING = "CALL_TYPE_OUTGOING"
31CALL_TYPE_INCOMING = "CALL_TYPE_INCOMING"
32default_timeout = 20
33
34class BtCarHfpTest(BluetoothBaseTest):
35 def setup_class(self):
36 self.hf = self.android_devices[0]
37 self.ag = self.android_devices[1]
38 self.re = self.android_devices[2]
39 self.ag_phone_number = "tel:{}".format(
40 self.ag.droid.telephonyGetLine1Number())
41 self.re_phone_number = "tel:{}".format(
42 self.re.droid.telephonyGetLine1Number())
43 self.log.info("ag tel: {} re tel: {}".format(
44 self.ag_phone_number, self.re_phone_number))
45
46 # Setup includes pairing and connecting the devices.
47 bt_test_utils.setup_multiple_devices_for_bt_test([self.hf, self.ag])
48 bt_test_utils.reset_bluetooth([self.hf, self.ag])
49
50 # Pair and connect the devices.
51 if not bt_test_utils.pair_pri_to_sec(self.hf.droid, self.ag.droid):
52 self.log.error("Failed to pair")
53 return False
54
55 # Connect the devices now, try twice.
56 attempts = 2
57 connected = False
58 while attempts > 0 and not connected:
59 connected = bt_test_utils.connect_pri_to_sec(
60 self.log, self.hf, self.ag.droid,
61 set([BtEnum.BluetoothProfile.HEADSET_CLIENT.value]))
62 self.log.info("Connected {}".format(connected))
63 attempts -= 1
64 return connected
65
66 def setup_test(self):
67 # Reset the devices.
68 self.log.debug(
69 bt_test_utils.log_energy_info(self.android_devices, "Start"))
70 for d in self.android_devices:
71 d.ed.clear_all_events()
72
73 def on_fail(self, test_name, begin_time):
74 self.log.debug("Test {} failed.".format(test_name))
75
76 def teardown_test(self):
77 self.log.debug(
78 bt_test_utils.log_energy_info(self.android_devices, "End"))
79
80 @BluetoothBaseTest.bt_test_wrap
81 def test_default_calling_account(self):
82 """
83 Tests if the default calling account is coming from the
84 bluetooth pacakge.
85
86 Precondition:
87 1. Devices are connected.
88
89 Steps:
90 1. Check if the default calling account is via Bluetooth package.
91
92 Returns:
93 Pass if True
94 Fail if False
95
96 Priority: 0
97 """
98 selected_acc = \
99 self.hf.droid.telecomGetUserSelectedOutgoingPhoneAccount()
100 if not selected_acc:
101 self.log.info("No default account found.")
102 return False
103
104 # Check if the default account is from the Bluetooth package. This is a
105 # light weight check.
106 try:
107 acc_component_id = selected_acc['ComponentName']
108 except KeyError:
109 self.log.info(
110 "No component name for account {}".format(selected_acc))
111 return False
112 if not acc_component_id.startswith(BLUETOOTH_PKG_NAME):
113 self.log.info(
114 "Component name does not start with pkg name {}".format(
115 selected_acc))
116 return False
117
118 @BluetoothBaseTest.bt_test_wrap
119 def test_outgoing_call_hf(self):
120 """
121 Tests if we can make a phone call from HF role and disconnect from HF
122 role.
123
124 Precondition:
125 1. Devices are connected.
126
127 Steps:
128 1. Make a call from HF role.
129 2. Wait for the HF, AG to be dialing and RE to see the call ringing.
130 3. Hangup the call on HF 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.hf, self.hf)
140
141
142 @BluetoothBaseTest.bt_test_wrap
143 def test_outgoing_call_ag(self):
144 """
145 Tests if we can make a phone call from AG role and disconnect from AG
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 be in dialing and RE to see the call ringing.
154 3. Hangup the call on AG 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.ag)
164
165 @BluetoothBaseTest.bt_test_wrap
166 def test_outgoing_dial_ag_hangup_hf(self):
167 """
168 Tests if we can make a phone call from AG role and disconnect from HF
169 role.
170
171 Precondition:
172 1. Devices are connected.
173
174 Steps:
175 1. Make a call from AG role.
176 2. Wait for the HF, AG to show dialing and RE to see the call ringing.
177 3. Hangup the call on HF role.
178 4. Wait for all devices to hangup the call.
179
180 Returns:
181 Pass if True
182 Fail if False
183
184 Priority: 0
185 """
186 return self.dial_a_hangup_b(self.ag, self.hf)
187
188 @BluetoothBaseTest.bt_test_wrap
189 def test_outgoing_dial_hf_hangup_ag(self):
190 """
191 Tests if we can make a phone call from HF role and disconnect from AG
192 role.
193
194 Precondition:
195 1. Devices are connected.
196
197 Steps:
198 1. Make a call from HF role.
199 2. Wait for the HF, AG to show dialing and RE to see the call ringing.
200 3. Hangup the call on AG role.
201 4. Wait for all devices to hangup the call.
202
203 Returns:
204 Pass if True
205 Fail if False
206
207 Priority: 0
208 """
209 return self.dial_a_hangup_b(self.hf, self.ag)
210
211 @BluetoothBaseTest.bt_test_wrap
212 def test_incoming_dial_re_hangup_re(self):
213 """
214 Tests if we can make a phone call from remote and disconnect from
215 remote.
216
217 Precondition:
218 1. Devices are connected.
219
220 Steps:
221 1. Make a call from RE role.
222 2. Wait for the HF, AG to show ringing and RE to see the call dialing.
223 3. Hangup the call on RE role.
224 4. Wait for all devices to hangup the call.
225
226 Returns:
227 Pass if True
228 Fail if False
229
230 Priority: 0
231 """
232 return self.dial_a_hangup_b(self.re, self.re, self.ag_phone_number)
233
234 def dial_a_hangup_b(self, a, b, ph=""):
235 """
236 a, b and c can be either of AG, HF or Remote.
237 1. Make a call from 'a' on a fixed number.
238 2. Wait for the call to get connected (check on both 'a' and 'b')
239 Check that 'c' is in ringing state.
240 3. Hangup the call on 'b'.
241 4. Wait for call to get completely disconnected
242 (check on both 'a' and 'b')
243 It is assumed that scenarios will not go into voice mail.
244 """
245 if ph == "": ph = self.re_phone_number
246
247 # Determine if this is outgoing or incoming call.
248 call_type = None
249 if a == self.ag or a == self.hf:
250 call_type = CALL_TYPE_OUTGOING
251 if b != self.ag and b != self.hf:
252 self.log.info("outgoing call should terminate at AG or HF")
253 return False
254 elif a == self.re:
255 call_type = CALL_TYPE_INCOMING
256 if b != self.re:
257 self.log.info("Incoming call should terminate at Re")
258 return False
259
260 self.log.info("Call type is {}".format(call_type))
261
262 # make a call on 'a'
263 if not car_telecom_utils.dial_number(self.log, a, ph):
264 return False
265
266 # Check that everyone is in dialing/ringing state.
267 ret = True
268 if call_type == CALL_TYPE_OUTGOING:
269 ret &= car_telecom_utils.wait_for_dialing(self.log, self.hf)
270 ret &= car_telecom_utils.wait_for_dialing(self.log, self.ag)
271 ret &= car_telecom_utils.wait_for_ringing(self.log, self.re)
272 else:
273 ret &= car_telecom_utils.wait_for_ringing(self.log, self.hf)
274 ret &= car_telecom_utils.wait_for_ringing(self.log, self.ag)
275 ret &= car_telecom_utils.wait_for_dialing(self.log, self.re)
276 if not ret:
277 return False
278
279 # Check if we have any calls with dialing or active state on 'b'.
280 # We assume we never disconnect from 'ringing' state since it will lead
281 # to voicemail.
282 call_state_dialing_or_active = \
283 [tel_defines.CALL_STATE_CONNECTING,
284 tel_defines.CALL_STATE_DIALING,
285 tel_defines.CALL_STATE_ACTIVE]
286
287 calls_in_dialing_or_active = car_telecom_utils.get_calls_in_states(
288 self.log, b, call_state_dialing_or_active)
289
290 # Make sure there is only one!
291 if len(calls_in_dialing_or_active) != 1:
292 self.log.info("Call State in dialing or active failed {}".format(
293 calls_in_dialing_or_active))
294 return False
295
296 # Hangup the *only* call on 'b'
297 if not car_telecom_utils.hangup_call(
298 self.log, b, calls_in_dialing_or_active[0]):
299 return False
300
301 # Make sure everyone got out of in call state.
302 for d in self.android_devices:
303 ret &= car_telecom_utils.wait_for_not_in_call(self.log, d)
304 return ret