blob: 93013dde225ecdf8619d926345594eef850d6667 [file] [log] [blame]
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -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"""Test script to test PBAP contact download between two devices which can run SL4A.
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070017"""
18
Joseph Pirozzof304d362016-06-17 15:15:40 -070019from time import sleep
20from time import time
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070021
22from acts.base_test import BaseTestClass
Sanket Agarwalbd9689b2016-08-24 11:14:53 -070023from acts.test_utils.bt import bt_contacts_utils
Joseph Pirozzof304d362016-06-17 15:15:40 -070024from acts.test_utils.bt import bt_test_utils
Sanket Agarwalbd9689b2016-08-24 11:14:53 -070025from acts.test_utils.car import car_bt_utils
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070026from acts.utils import exe_cmd
Joseph Pirozzof304d362016-06-17 15:15:40 -070027import acts.test_utils.bt.BtEnum as BtEnum
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070028
Joseph Pirozzof304d362016-06-17 15:15:40 -070029# Names for temporary files for contacts cards for import and export from PSE and PCE
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070030PSE_CONTACTS_FILE = "psecontacts.vcf"
31PCE_CONTACTS_FILE = "pcecontacts.vcf"
Joseph Pirozzof304d362016-06-17 15:15:40 -070032
33# Offset call logs by 1 minute
34CALL_LOG_TIME_OFFSET_IN_MSEC = 60000
35
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070036
37class BtCarPbapTest(BaseTestClass):
38 def __init__(self, controllers):
39 BaseTestClass.__init__(self, controllers)
40 self.pce = self.android_devices[0]
41 self.pse = self.android_devices[1]
42
43 def setup_class(self):
44 # Reset the devices in a clean state.
Sanket Agarwalbd9689b2016-08-24 11:14:53 -070045 bt_test_utils.setup_multiple_devices_for_bt_test([self.pce, self.pse])
Joseph Pirozzof304d362016-06-17 15:15:40 -070046 bt_test_utils.reset_bluetooth(self.android_devices)
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070047
48 for a in self.android_devices:
49 a.ed.clear_all_events()
50
51 # Pair the devices.
52 # This call may block until some specified timeout in bt_test_utils.py.
Joseph Pirozzof304d362016-06-17 15:15:40 -070053 if not bt_test_utils.pair_pri_to_sec(self.pce.droid, self.pse.droid):
54 self.log.error("Failed to pair.")
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070055 return False
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070056
Sanket Agarwalbd9689b2016-08-24 11:14:53 -070057 # Disable the HFP and A2DP profiles. This will ensure only PBAP
58 # gets connected. Also, this will eliminate the auto-connect loop.
59 car_bt_utils.set_car_profile_priorities_off(self.pce, self.pse)
60
61 # Enable PBAP on PSE & PCE.
62 bt_test_utils.set_profile_priority(
63 self.pce, self.pse, [BtEnum.BluetoothProfile.PBAP_CLIENT],
64 BtEnum.BluetoothPriorityLevel.PRIORITY_ON)
65
Joseph Pirozzof304d362016-06-17 15:15:40 -070066 self.pse.droid.bluetoothChangeProfileAccessPermission(
67 self.pce.droid.bluetoothGetLocalAddress(),
68 BtEnum.BluetoothProfile.PBAP_SERVER.value,
69 BtEnum.BluetoothAccessLevel.ACCESS_ALLOWED.value)
70
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070071 return True
72
73 def setup_test(self):
74 bt_contacts_utils.set_logger(self.log)
Joseph Pirozzof304d362016-06-17 15:15:40 -070075 self.pse.droid.callLogsEraseAll()
76 if not (bt_contacts_utils.erase_contacts(self.pse) and
77 bt_contacts_utils.erase_contacts(self.pce)):
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070078 return False
Joseph Pirozzof304d362016-06-17 15:15:40 -070079 # Allow all content providers to synchronize.
80 sleep(1)
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070081 return True
82
83 def teardown_test(self):
Joseph Pirozzof304d362016-06-17 15:15:40 -070084 self.pce.droid.bluetoothPbapClientDisconnect(
85 self.pse.droid.bluetoothGetLocalAddress())
86 bt_contacts_utils.erase_contacts(self.pse)
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070087 return True
88
89 def on_fail(self, test_name, begin_time):
Joseph Pirozzof304d362016-06-17 15:15:40 -070090 bt_test_utils.take_btsnoop_logs(self.android_devices, self, test_name)
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -070091
Joseph Pirozzof304d362016-06-17 15:15:40 -070092 def verify_contacts_match(self):
93 bt_contacts_utils.export_device_contacts_to_vcf(self.pce,
94 PCE_CONTACTS_FILE)
95 return bt_contacts_utils.count_contacts_with_differences(
96 PCE_CONTACTS_FILE, PSE_CONTACTS_FILE) == 0
97
98 def connect_and_verify(self, count):
99 bt_test_utils.connect_pri_to_sec(
100 self.log, self.pce, self.pse.droid,
101 set([BtEnum.BluetoothProfile.PBAP_CLIENT.value]))
102 bt_contacts_utils.wait_for_phone_number_update_complete(self.pce,
103 count)
104 contacts_added = self.verify_contacts_match()
105 self.pce.droid.bluetoothPbapClientDisconnect(
106 self.pse.droid.bluetoothGetLocalAddress())
107 contacts_removed = bt_contacts_utils.wait_for_phone_number_update_complete(
108 self.pce, 0)
109 return contacts_added and contacts_removed
110
111 def test_pbap_connect_and_disconnect(self):
112 """Test Connectivity
113
114 Test connecting with the server enabled and disabled
115
116 Precondition:
117 1. Devices are paired.
118
119 Steps:
120 1. Disable permission on PSE to prevent PCE from connecting
121 2. Attempt to connect PCE to PSE
122 3. Verify connection failed
123 4. Enable permission on PSE to allow PCE to connect
124 5. Attempt to connect PCE to PSE
125 6. Verify connection succeeded
126
127 Returns:
128 Pass if True
129 Fail if False
130 """
131 self.pse.droid.bluetoothChangeProfileAccessPermission(
132 self.pce.droid.bluetoothGetLocalAddress(),
133 BtEnum.BluetoothProfile.PBAP_SERVER.value,
134 BtEnum.BluetoothAccessLevel.ACCESS_DENIED.value)
135 if bt_test_utils.connect_pri_to_sec(
136 self.log, self.pce, self.pse.droid,
137 set([BtEnum.BluetoothProfile.PBAP_CLIENT.value])):
138 self.log.error("Client connected and shouldn't be.")
139 return False
Sanket Agarwalbd9689b2016-08-24 11:14:53 -0700140
Joseph Pirozzof304d362016-06-17 15:15:40 -0700141 self.pce.droid.bluetoothPbapClientDisconnect(
142 self.pse.droid.bluetoothGetLocalAddress())
143
144 self.pse.droid.bluetoothChangeProfileAccessPermission(
145 self.pce.droid.bluetoothGetLocalAddress(),
146 BtEnum.BluetoothProfile.PBAP_SERVER.value,
147 BtEnum.BluetoothAccessLevel.ACCESS_ALLOWED.value)
Sanket Agarwalbd9689b2016-08-24 11:14:53 -0700148
Joseph Pirozzof304d362016-06-17 15:15:40 -0700149 if not bt_test_utils.connect_pri_to_sec(
150 self.log, self.pce, self.pse.droid,
151 set([BtEnum.BluetoothProfile.PBAP_CLIENT.value])):
152 self.log.error("No client connected and should be.")
153 return False
154
155 return True
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -0700156
157 def test_contact_download(self):
158 """Test Contact Download
159
160 Test download of contacts from a clean state.
161
Joseph Pirozzof304d362016-06-17 15:15:40 -0700162 Precondition:
163 1. Devices are paired.
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -0700164
Joseph Pirozzof304d362016-06-17 15:15:40 -0700165 Steps:
166 1. Erase contacts from PSE and PCE.
167 2. Add a predefined list of contacts to PSE.
168 3. Connect PCE to PSE to perform transfer.
169 4. Compare transfered contacts.
170 5. Disconnect.
171 6. Verify PCE cleaned up contact list.
172
173 Returns:
174 Pass if True
175 Fail if False
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -0700176 """
Joseph Pirozzof304d362016-06-17 15:15:40 -0700177 bt_contacts_utils.generate_contact_list(PSE_CONTACTS_FILE, 100)
178 phone_numbers_added = bt_contacts_utils.import_device_contacts_from_vcf(
179 self.pse, PSE_CONTACTS_FILE)
180 bt_test_utils.connect_pri_to_sec(
181 self.log, self.pce, self.pse.droid,
182 set([BtEnum.BluetoothProfile.PBAP_CLIENT.value]))
183 bt_contacts_utils.wait_for_phone_number_update_complete(
184 self.pce, phone_numbers_added)
185 if not self.verify_contacts_match():
186 return False
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -0700187 self.pce.droid.bluetoothPbapClientDisconnect(
188 self.pse.droid.bluetoothGetLocalAddress())
Joseph Pirozzof304d362016-06-17 15:15:40 -0700189 return bt_contacts_utils.wait_for_phone_number_update_complete(
190 self.pce, 0)
191
192 def test_modify_phonebook(self):
193 """Test Modify Phonebook
194
195 Test changing contacts and reconnecting PBAP.
196
197 Precondition:
198 1. Devices are paired.
199
200 Steps:
201 1. Add a predefined list of contacts to PSE.
202 2. Connect PCE to PSE to perform transfer.
203 3. Verify that contacts match.
204 4. Change some contacts on the PSE.
205 5. Reconnect PCE to PSE to perform transfer.
206 6. Verify that new contacts match.
207
208 Returns:
209 Pass if True
210 Fail if False
211 """
212 bt_contacts_utils.generate_contact_list(PSE_CONTACTS_FILE, 100)
213 phone_numbers_added = bt_contacts_utils.import_device_contacts_from_vcf(
214 self.pse, PSE_CONTACTS_FILE)
215 if not self.connect_and_verify(phone_numbers_added):
216 return False
217
Joseph Pirozzo66fb3f62016-05-31 16:57:39 -0700218 bt_contacts_utils.erase_contacts(self.pse)
Joseph Pirozzof304d362016-06-17 15:15:40 -0700219 bt_contacts_utils.generate_contact_list(PSE_CONTACTS_FILE, 110, 2)
220 phone_numbers_added = bt_contacts_utils.import_device_contacts_from_vcf(
221 self.pse, PSE_CONTACTS_FILE)
222 return self.connect_and_verify(phone_numbers_added)
223
224 def test_special_contacts(self):
225 """Test Special Contacts
226
227 Test numerous special cases of contacts that could cause errors.
228
229 Precondition:
230 1. Devices are paired.
231
232 Steps:
233 1. Add a predefined list of contacts to PSE that includes special cases:
234 2. Connect PCE to PSE to perform transfer.
235 3. Verify that contacts match.
236
237 Returns:
238 Pass if True
239 Fail if False
240 """
241
242 vcards = []
243
244 # Generate a contact with no email address
245 current_contact = bt_contacts_utils.VCard()
246 current_contact.first_name = "Mr."
247 current_contact.last_name = "Smiley"
248 current_contact.add_phone_number(
249 bt_contacts_utils.generate_random_phone_number())
250 vcards.append(current_contact)
251
252 # Generate a 2nd contact with the same name but different phone number
253 current_contact = bt_contacts_utils.VCard()
254 current_contact.first_name = "Mr."
255 current_contact.last_name = "Smiley"
256 current_contact.add_phone_number(
257 bt_contacts_utils.generate_random_phone_number())
258 vcards.append(current_contact)
259
260 # Generate a contact with no name
261 current_contact = bt_contacts_utils.VCard()
262 current_contact.email = "{}@gmail.com".format(
263 bt_contacts_utils.generate_random_string())
264 current_contact.add_phone_number(
265 bt_contacts_utils.generate_random_phone_number())
266 vcards.append(current_contact)
267
268 # Generate a contact with random characters in its name
269 current_contact = bt_contacts_utils.VCard()
270 current_contact.first_name = bt_contacts_utils.generate_random_string()
271 current_contact.last_name = bt_contacts_utils.generate_random_string()
272 current_contact.add_phone_number(
273 bt_contacts_utils.generate_random_phone_number())
274 vcards.append(current_contact)
275
276 # Generate a contact with only a phone number
277 current_contact = bt_contacts_utils.VCard()
278 current_contact.add_phone_number(
279 bt_contacts_utils.generate_random_phone_number())
280 vcards.append(current_contact)
281
282 # Generate a 2nd contact with only a phone number
283 current_contact = bt_contacts_utils.VCard()
284 current_contact.add_phone_number(
285 bt_contacts_utils.generate_random_phone_number())
286 vcards.append(current_contact)
287
288 bt_contacts_utils.create_new_contacts_vcf_from_vcards(
289 PSE_CONTACTS_FILE, vcards)
290
291 phone_numbers_added = bt_contacts_utils.import_device_contacts_from_vcf(
292 self.pse, PSE_CONTACTS_FILE)
293
294 return self.connect_and_verify(phone_numbers_added)
295
296 def test_call_log(self):
297 """Test Call Log
298
299 Test that Call Logs are transfered
300
301 Precondition:
302 1. Devices are paired.
303
304 Steps:
305 1. Add a predefined list of calls to the PSE call log.
306 2. Connect PCE to PSE to allow call log transfer
307 3. Verify the Missed, Incoming, and Outgoing Call History
308
309 Returns:
310 Pass if True
311 Fail if False
312 """
313
314 bt_contacts_utils.add_call_log(
315 self.pse, bt_contacts_utils.INCOMMING_CALL_TYPE,
316 bt_contacts_utils.generate_random_phone_number().phone_number,
317 int(time()) * 1000)
318 bt_contacts_utils.add_call_log(
319 self.pse, bt_contacts_utils.INCOMMING_CALL_TYPE,
320 bt_contacts_utils.generate_random_phone_number().phone_number,
321 int(time()) * 1000 - 4 * CALL_LOG_TIME_OFFSET_IN_MSEC)
322 bt_contacts_utils.add_call_log(
323 self.pse, bt_contacts_utils.OUTGOING_CALL_TYPE,
324 bt_contacts_utils.generate_random_phone_number().phone_number,
325 int(time()) * 1000 - CALL_LOG_TIME_OFFSET_IN_MSEC)
326 bt_contacts_utils.add_call_log(
327 self.pse, bt_contacts_utils.MISSED_CALL_TYPE,
328 bt_contacts_utils.generate_random_phone_number().phone_number,
329 int(time()) * 1000 - 2 * CALL_LOG_TIME_OFFSET_IN_MSEC)
330 bt_contacts_utils.add_call_log(
331 self.pse, bt_contacts_utils.MISSED_CALL_TYPE,
332 bt_contacts_utils.generate_random_phone_number().phone_number,
333 int(time()) * 1000 - 2 * CALL_LOG_TIME_OFFSET_IN_MSEC)
334
335 bt_test_utils.connect_pri_to_sec(
336 self.log, self.pce, self.pse.droid,
337 set([BtEnum.BluetoothProfile.PBAP_CLIENT.value]))
338 pse_call_log_count = self.pse.droid.callLogGetCount()
339 self.log.info("Waiting for {} call logs to be transfered".format(
340 pse_call_log_count))
341 bt_contacts_utils.wait_for_call_log_update_complete(self.pce,
342 pse_call_log_count)
343
344 if not bt_contacts_utils.get_and_compare_call_logs(
345 self.pse, self.pce, bt_contacts_utils.INCOMMING_CALL_TYPE):
346 return False
347 if not bt_contacts_utils.get_and_compare_call_logs(
348 self.pse, self.pce, bt_contacts_utils.OUTGOING_CALL_TYPE):
349 return False
350 if not bt_contacts_utils.get_and_compare_call_logs(
351 self.pse, self.pce, bt_contacts_utils.MISSED_CALL_TYPE):
352 return False
353
354 return True