1#/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""" 17This test script exercises different GATT write procedures. 18""" 19 20from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest 21from acts.test_utils.bt.GattConnectedBaseTest import GattConnectedBaseTest 22from acts.test_utils.bt.GattEnum import GattCharacteristic 23from acts.test_utils.bt.GattEnum import GattDescriptor 24from acts.test_utils.bt.GattEnum import MtuSize 25from acts.test_utils.bt.GattEnum import GattEvent 26from acts.test_utils.bt.GattEnum import GattCbStrings 27from acts.test_utils.bt.GattEnum import GattConnectionPriority 28 29 30class GattWriteTest(GattConnectedBaseTest): 31 @BluetoothBaseTest.bt_test_wrap 32 def test_write_char(self): 33 """Test write characteristic value 34 35 Test write characteristic value using Write Request 36 37 1. Central: write WRITABLE_CHAR_UUID characteristic with char_value 38 using write request. 39 2. Peripheral: receive the written data. 40 3. Peripheral: send response with status 0 (success). 41 4. Central: make sure write callback is called. 42 43 Expected Result: 44 Verify that write request/response is properly delivered. 45 46 Returns: 47 Pass if True 48 Fail if False 49 50 TAGS: LE, GATT, Characteristic 51 Priority: 0 52 """ 53 char_value = [1, 2, 3, 4, 5, 6, 7] 54 self.cen_ad.droid.gattClientCharacteristicSetValue( 55 self.bluetooth_gatt, self.discovered_services_index, 56 self.test_service_index, self.WRITABLE_CHAR_UUID, char_value) 57 58 self.cen_ad.droid.gattClientCharacteristicSetWriteType( 59 self.bluetooth_gatt, self.discovered_services_index, 60 self.test_service_index, self.WRITABLE_CHAR_UUID, 61 GattCharacteristic.WRITE_TYPE_DEFAULT.value) 62 63 self.cen_ad.droid.gattClientWriteCharacteristic( 64 self.bluetooth_gatt, self.discovered_services_index, 65 self.test_service_index, self.WRITABLE_CHAR_UUID) 66 67 event = self._server_wait(GattEvent.CHAR_WRITE_REQ) 68 69 request_id = event['data']['requestId'] 70 self.assertEqual(True, event['data']['responseNeeded'], 71 "Should need response") 72 self.assertEqual(char_value, event['data']['value']) 73 self.assertEqual(0, event['data']['offset']) 74 75 bt_device_id = 0 76 status = 0 77 #both offset and return value don't matter, just the status 78 offset = 0 79 self.per_ad.droid.gattServerGetConnectedDevices(self.gatt_server) 80 self.per_ad.droid.gattServerSendResponse( 81 self.gatt_server, bt_device_id, request_id, status, offset, []) 82 83 event = self._client_wait(GattEvent.CHAR_WRITE) 84 self.assertEqual(status, event["data"]["Status"], 85 "Write status should be 0") 86 # Write response doesn't carry any data expcept status 87 return True 88 89 @BluetoothBaseTest.bt_test_wrap 90 def test_write_descr(self): 91 """Test write descriptor value 92 93 Test write descriptor value 94 95 1. Central: write WRITABLE_DESC_UUID descriptor with desc_value. 96 2. Peripheral: receive the written data. 97 3. Peripheral: send response with status 0 (success). 98 4. Central: make sure write callback is called. 99 100 Expected Result: 101 Verify that write request/response is properly delivered. 102 103 Returns: 104 Pass if True 105 Fail if False 106 107 TAGS: LE, GATT, Descriptor 108 Priority: 0 109 """ 110 desc_value = [1, 2, 3, 4, 5, 6, 7] 111 self.cen_ad.droid.gattClientDescriptorSetValue( 112 self.bluetooth_gatt, self.discovered_services_index, 113 self.test_service_index, self.WRITABLE_CHAR_UUID, 114 self.WRITABLE_DESC_UUID, desc_value) 115 116 self.cen_ad.droid.gattClientWriteDescriptor( 117 self.bluetooth_gatt, self.discovered_services_index, 118 self.test_service_index, self.WRITABLE_CHAR_UUID, 119 self.WRITABLE_DESC_UUID) 120 121 event = self._server_wait(GattEvent.DESC_WRITE_REQ) 122 123 request_id = event['data']['requestId'] 124 self.assertEqual(True, event['data']['responseNeeded'], 125 "Should need response") 126 self.assertEqual(desc_value, event['data']['value']) 127 self.assertEqual(0, event['data']['offset']) 128 129 bt_device_id = 0 130 status = 0 131 #both offset and return value don't matter, just the status 132 offset = 0 133 self.per_ad.droid.gattServerGetConnectedDevices(self.gatt_server) 134 self.per_ad.droid.gattServerSendResponse( 135 self.gatt_server, bt_device_id, request_id, status, offset, []) 136 137 event = self._client_wait(GattEvent.DESC_WRITE) 138 self.assertEqual(status, event["data"]["Status"], 139 "Write status should be 0") 140 # Write response doesn't carry any data except status 141 return True 142 143 @BluetoothBaseTest.bt_test_wrap 144 def test_write_char_no_resp(self): 145 """Test write characteristic value 146 147 Test write characteristic value using Write Command 148 149 1. Central: write WRITABLE_CHAR_UUID characteristic with char_value 150 using write command. 151 2. Central: make sure write callback is called. 152 3. Peripheral: receive the written data. 153 154 Expected Result: 155 Verify that write command is properly delivered. 156 157 Returns: 158 Pass if True 159 Fail if False 160 161 TAGS: LE, GATT, Characteristic 162 Priority: 0 163 """ 164 char_value = [1, 2, 3, 4, 5, 6, 7] 165 self.cen_ad.droid.gattClientCharacteristicSetValue( 166 self.bluetooth_gatt, self.discovered_services_index, 167 self.test_service_index, self.WRITABLE_CHAR_UUID, char_value) 168 169 self.cen_ad.droid.gattClientCharacteristicSetWriteType( 170 self.bluetooth_gatt, self.discovered_services_index, 171 self.test_service_index, self.WRITABLE_CHAR_UUID, 172 GattCharacteristic.WRITE_TYPE_NO_RESPONSE.value) 173 174 self.cen_ad.droid.gattClientWriteCharacteristic( 175 self.bluetooth_gatt, self.discovered_services_index, 176 self.test_service_index, self.WRITABLE_CHAR_UUID) 177 178 event = self._client_wait(GattEvent.CHAR_WRITE) 179 if event["data"]["Status"] != 0: 180 self.log.error("Write status should be 0") 181 return False 182 183 event = self._server_wait(GattEvent.CHAR_WRITE_REQ) 184 185 request_id = event['data']['requestId'] 186 self.assertEqual(False, event['data']['responseNeeded'], 187 "Should not need response") 188 self.assertEqual(0, event['data']['offset']) 189 self.assertEqual(char_value, event['data']['value']) 190 191 return True 192 193 @BluetoothBaseTest.bt_test_wrap 194 def test_write_characteristic_long_no_resp(self): 195 """Test write characteristic value 196 197 Test write characteristic value using Write Command 198 199 1. Central: write WRITABLE_CHAR_UUID characteristic with char_value 200 using write command. 201 2. Central: make sure write callback is called. 202 3. Peripheral: receive the written data. Check it was properly trimmed. 203 204 Expected Result: 205 Verify that write command is properly trimmed and delivered. 206 207 Returns: 208 Pass if True 209 Fail if False 210 211 TAGS: LE, GATT, Characteristic 212 Priority: 0 213 """ 214 char_value = [] 215 for i in range(512): 216 char_value.append(i % 256) 217 218 self.cen_ad.droid.gattClientCharacteristicSetValue( 219 self.bluetooth_gatt, self.discovered_services_index, 220 self.test_service_index, self.WRITABLE_CHAR_UUID, char_value) 221 222 self.cen_ad.droid.gattClientCharacteristicSetWriteType( 223 self.bluetooth_gatt, self.discovered_services_index, 224 self.test_service_index, self.WRITABLE_CHAR_UUID, 225 GattCharacteristic.WRITE_TYPE_NO_RESPONSE.value) 226 227 self.cen_ad.droid.gattClientWriteCharacteristic( 228 self.bluetooth_gatt, self.discovered_services_index, 229 self.test_service_index, self.WRITABLE_CHAR_UUID) 230 231 event = self._server_wait(GattEvent.CHAR_WRITE_REQ) 232 233 request_id = event['data']['requestId'] 234 self.assertEqual(False, event['data']['responseNeeded']) 235 236 # value shall be trimmed to MTU-3 237 trimmed_value = char_value[0:self.mtu - 3] 238 self.assertEqual( 239 trimmed_value, event['data']['value'], 240 "Received value should be sent value trimmed to MTU-3") 241 242 event = self._client_wait(GattEvent.CHAR_WRITE) 243 if event["data"]["Status"] != 0: 244 self.log.error("Write status should be 0") 245 return False 246 return True 247 248 @BluetoothBaseTest.bt_test_wrap 249 def test_write_characteristic_stress(self): 250 """Stress test write characteristic value 251 252 Test write characteristic value using Write Request 253 254 1. Central: write WRITABLE_CHAR_UUID characteristic with char_value 255 using write request. 256 2. Peripheral: receive the written data. 257 3. Peripheral: send response with status 0 (success). 258 4. Central: make sure write callback is called. 259 5. Repeat steps 1-4 100 times. 260 261 Expected Result: 262 Verify that write request/response is properly delivered. 263 264 Returns: 265 Pass if True 266 Fail if False 267 268 TAGS: LE, GATT, Characteristic 269 Priority: 0 270 """ 271 self.cen_ad.droid.gattClientRequestConnectionPriority( 272 self.bluetooth_gatt, 273 GattConnectionPriority.CONNECTION_PRIORITY_HIGH.value) 274 275 bt_device_id = 0 276 277 self.cen_ad.droid.gattClientCharacteristicSetWriteType( 278 self.bluetooth_gatt, self.discovered_services_index, 279 self.test_service_index, self.WRITABLE_CHAR_UUID, 280 GattCharacteristic.WRITE_TYPE_DEFAULT.value) 281 282 for i in range(100): 283 284 char_value = [] 285 for j in range(i, i + self.mtu - 3): 286 char_value.append(j % 256) 287 288 self.cen_ad.droid.gattClientCharacteristicSetValue( 289 self.bluetooth_gatt, self.discovered_services_index, 290 self.test_service_index, self.WRITABLE_CHAR_UUID, char_value) 291 292 self.cen_ad.droid.gattClientWriteCharacteristic( 293 self.bluetooth_gatt, self.discovered_services_index, 294 self.test_service_index, self.WRITABLE_CHAR_UUID) 295 296 event = self._server_wait(GattEvent.CHAR_WRITE_REQ) 297 298 self.log.info("{} event found: {}".format( 299 GattCbStrings.CHAR_WRITE_REQ.value.format( 300 self.gatt_server_callback), event['data']['value'])) 301 request_id = event['data']['requestId'] 302 found_value = event['data']['value'] 303 if found_value != char_value: 304 self.log.info("Values didn't match. Found: {}, " 305 "Expected: {}".format(found_value, char_value)) 306 return False 307 308 # only status is sent 309 status = 0 310 offset = 0 311 char_value_return = [] 312 self.per_ad.droid.gattServerSendResponse( 313 self.gatt_server, bt_device_id, request_id, status, offset, 314 char_value_return) 315 316 event = self._client_wait(GattEvent.CHAR_WRITE) 317 if event["data"]["Status"] != status: 318 self.log.error("Write status should be 0") 319 return False 320 321 return True 322 323 @BluetoothBaseTest.bt_test_wrap 324 def test_write_descriptor_stress(self): 325 """Stress test write descriptor value 326 327 Stress test write descriptor value 328 329 1. Central: write WRITABLE_DESC_UUID descriptor with desc_value. 330 2. Peripheral: receive the written data. 331 3. Peripheral: send response with status 0 (success). 332 4. Central: make sure write callback is called. 333 5. Repeat 1-4 100 times 334 335 Expected Result: 336 Verify that write request/response is properly delivered. 337 338 Returns: 339 Pass if True 340 Fail if False 341 342 TAGS: LE, GATT, Descriptor 343 Priority: 0 344 """ 345 self.cen_ad.droid.gattClientRequestConnectionPriority( 346 self.bluetooth_gatt, 347 GattConnectionPriority.CONNECTION_PRIORITY_HIGH.value) 348 349 for i in range(100): 350 351 desc_value = [] 352 for j in range(i, i + self.mtu - 3): 353 desc_value.append(j % 256) 354 355 self.cen_ad.droid.gattClientDescriptorSetValue( 356 self.bluetooth_gatt, self.discovered_services_index, 357 self.test_service_index, self.WRITABLE_CHAR_UUID, 358 self.WRITABLE_DESC_UUID, desc_value) 359 360 self.cen_ad.droid.gattClientWriteDescriptor( 361 self.bluetooth_gatt, self.discovered_services_index, 362 self.test_service_index, self.WRITABLE_CHAR_UUID, 363 self.WRITABLE_DESC_UUID) 364 365 event = self._server_wait(GattEvent.DESC_WRITE_REQ) 366 367 self.log.info("{} event found: {}".format( 368 GattCbStrings.CHAR_WRITE_REQ.value.format( 369 self.gatt_server_callback), event['data']['value'])) 370 371 request_id = event['data']['requestId'] 372 self.assertEqual(True, event['data']['responseNeeded'], 373 "Should need response") 374 self.assertEqual(desc_value, event['data']['value']) 375 self.assertEqual(0, event['data']['offset']) 376 377 bt_device_id = 0 378 status = 0 379 #both offset and return value don't matter, just the status 380 offset = 0 381 self.per_ad.droid.gattServerGetConnectedDevices(self.gatt_server) 382 self.per_ad.droid.gattServerSendResponse( 383 self.gatt_server, bt_device_id, request_id, status, offset, []) 384 385 event = self._client_wait(GattEvent.DESC_WRITE) 386 self.assertEqual(status, event["data"]["Status"], 387 "Write status should be 0") 388 # Write response doesn't carry any data except status 389 return True 390 391 @BluetoothBaseTest.bt_test_wrap 392 def test_write_characteristic_no_resp_stress(self): 393 """Stress test write characteristic value 394 395 Stress test write characteristic value using Write Command 396 397 1. Central: write WRITABLE_CHAR_UUID characteristic with char_value 398 using write command. 399 2. Central: make sure write callback is called. 400 3. Peripheral: receive the written data. 401 4. Repeat steps 1-3 100 times. 402 403 Expected Result: 404 Verify that write command is properly delivered. 405 406 Returns: 407 Pass if True 408 Fail if False 409 410 TAGS: LE, GATT, Characteristic 411 Priority: 0 412 """ 413 self.cen_ad.droid.gattClientRequestConnectionPriority( 414 self.bluetooth_gatt, 415 GattConnectionPriority.CONNECTION_PRIORITY_HIGH.value) 416 417 bt_device_id = 0 418 419 self.cen_ad.droid.gattClientCharacteristicSetWriteType( 420 self.bluetooth_gatt, self.discovered_services_index, 421 self.test_service_index, self.WRITABLE_CHAR_UUID, 422 GattCharacteristic.WRITE_TYPE_NO_RESPONSE.value) 423 424 for i in range(100): 425 char_value = [] 426 for j in range(i, i + self.mtu - 3): 427 char_value.append(j % 256) 428 429 self.cen_ad.droid.gattClientCharacteristicSetValue( 430 self.bluetooth_gatt, self.discovered_services_index, 431 self.test_service_index, self.WRITABLE_CHAR_UUID, char_value) 432 433 self.cen_ad.droid.gattClientWriteCharacteristic( 434 self.bluetooth_gatt, self.discovered_services_index, 435 self.test_service_index, self.WRITABLE_CHAR_UUID) 436 437 # client shall not wait for server, get complete event right away 438 event = self._client_wait(GattEvent.CHAR_WRITE) 439 if event["data"]["Status"] != 0: 440 self.log.error("Write status should be 0") 441 return False 442 443 event = self._server_wait(GattEvent.CHAR_WRITE_REQ) 444 445 self.log.info("{} event found: {}".format( 446 GattCbStrings.CHAR_WRITE_REQ.value.format( 447 self.gatt_server_callback), event['data']['value'])) 448 request_id = event['data']['requestId'] 449 found_value = event['data']['value'] 450 if found_value != char_value: 451 self.log.info("Values didn't match. Found: {}, " 452 "Expected: {}".format(found_value, char_value)) 453 return False 454 455 return True 456