1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.verifier.bluetooth; 18 19 import android.app.Service; 20 import android.bluetooth.BluetoothDevice; 21 import android.bluetooth.BluetoothGatt; 22 import android.bluetooth.BluetoothGattCharacteristic; 23 import android.bluetooth.BluetoothGattDescriptor; 24 import android.bluetooth.BluetoothGattServer; 25 import android.bluetooth.BluetoothGattServerCallback; 26 import android.bluetooth.BluetoothGattService; 27 import android.bluetooth.BluetoothManager; 28 import android.bluetooth.BluetoothProfile; 29 import android.bluetooth.le.AdvertiseCallback; 30 import android.bluetooth.le.AdvertiseData; 31 import android.bluetooth.le.AdvertiseSettings; 32 import android.bluetooth.le.BluetoothLeAdvertiser; 33 import android.content.Context; 34 import android.content.Intent; 35 import android.os.Build; 36 import android.os.Handler; 37 import android.os.IBinder; 38 import android.os.ParcelUuid; 39 import android.util.Log; 40 import android.widget.Toast; 41 42 import com.android.cts.verifier.R; 43 44 import java.util.ArrayList; 45 import java.util.Arrays; 46 import java.util.HashMap; 47 import java.util.LinkedHashMap; 48 import java.util.List; 49 import java.util.Set; 50 import java.util.Timer; 51 import java.util.UUID; 52 53 public class BleServerService extends Service { 54 55 public static final boolean DEBUG = true; 56 public static final String TAG = "BleServerService"; 57 58 public static final int COMMAND_ADD_SERVICE = 0; 59 public static final int COMMAND_WRITE_CHARACTERISTIC = 1; 60 public static final int COMMAND_WRITE_DESCRIPTOR = 2; 61 62 public static final String BLE_BLUETOOTH_MISMATCH_SECURE = 63 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_MISMATCH_SECURE"; 64 public static final String BLE_BLUETOOTH_MISMATCH_INSECURE = 65 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_MISMATCH_INSECURE"; 66 public static final String BLE_BLUETOOTH_DISABLED = 67 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_DISABLED"; 68 public static final String BLE_ACTION_SERVER_SECURE = 69 "com.android.cts.verifier.bluetooth.BLE_ACTION_SERVER_SECURE"; 70 public static final String BLE_ACTION_SERVER_NON_SECURE = 71 "com.android.cts.verifier.bluetooth.BLE_ACTION_SERVER_NON_SECURE"; 72 73 74 public static final String BLE_SERVER_CONNECTED = 75 "com.android.cts.verifier.bluetooth.BLE_SERVER_CONNECTED"; 76 public static final String BLE_SERVER_DISCONNECTED = 77 "com.android.cts.verifier.bluetooth.BLE_SERVER_DISCONNECTED"; 78 public static final String BLE_SERVICE_ADDED = 79 "com.android.cts.verifier.bluetooth.BLE_SERVICE_ADDED"; 80 public static final String BLE_MTU_REQUEST_23BYTES = 81 "com.android.cts.verifier.bluetooth.BLE_MTU_REQUEST_23BYTES"; 82 public static final String BLE_MTU_REQUEST_512BYTES = 83 "com.android.cts.verifier.bluetooth.BLE_MTU_REQUEST_512BYTES"; 84 public static final String BLE_CHARACTERISTIC_READ_REQUEST = 85 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ_REQUEST"; 86 public static final String BLE_CHARACTERISTIC_WRITE_REQUEST = 87 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE_REQUEST"; 88 public static final String BLE_CHARACTERISTIC_READ_REQUEST_WITHOUT_PERMISSION = 89 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ_REQUEST_WITHOUT_PERMISSION"; 90 public static final String BLE_CHARACTERISTIC_WRITE_REQUEST_WITHOUT_PERMISSION = 91 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE_REQUEST_WITHOUT_PERMISSION"; 92 public static final String BLE_CHARACTERISTIC_READ_REQUEST_NEED_ENCRYPTED = 93 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ_REQUEST_NEED_ENCRYPTED"; 94 public static final String BLE_CHARACTERISTIC_WRITE_REQUEST_NEED_ENCRYPTED = 95 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE_REQUEST_NEED_ENCRYPTED"; 96 public static final String BLE_CHARACTERISTIC_NOTIFICATION_REQUEST = 97 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_NOTIFICATION_REQUEST"; 98 public static final String BLE_CHARACTERISTIC_INDICATE_REQUEST = 99 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_INDICATE_REQUEST"; 100 public static final String BLE_DESCRIPTOR_READ_REQUEST = 101 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ_REQUEST"; 102 public static final String BLE_DESCRIPTOR_WRITE_REQUEST = 103 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE_REQUEST"; 104 public static final String BLE_DESCRIPTOR_READ_REQUEST_WITHOUT_PERMISSION = 105 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ_REQUEST_WITHOUT_PERMISSION"; 106 public static final String BLE_DESCRIPTOR_WRITE_REQUEST_WITHOUT_PERMISSION = 107 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE_REQUEST_WITHOUT_PERMISSION"; 108 public static final String BLE_DESCRIPTOR_READ_REQUEST_NEED_ENCRYPTED = 109 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ_REQUEST_NEED_ENCRYPTED"; 110 public static final String BLE_DESCRIPTOR_WRITE_REQUEST_NEED_ENCRYPTED = 111 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE_REQUEST_NEED_ENCRYPTED"; 112 public static final String BLE_EXECUTE_WRITE = 113 "com.android.cts.verifier.bluetooth.BLE_EXECUTE_WRITE"; 114 public static final String BLE_OPEN_FAIL = 115 "com.android.cts.verifier.bluetooth.BLE_OPEN_FAIL"; 116 public static final String BLE_RELIABLE_WRITE_BAD_RESP = 117 "com.android.cts.verifier.bluetooth.BLE_RELIABLE_WRITE_BAD_RESP"; 118 public static final String BLE_ADVERTISE_UNSUPPORTED = 119 "com.android.cts.verifier.bluetooth.BLE_ADVERTISE_UNSUPPORTED"; 120 public static final String BLE_ADD_SERVICE_FAIL = 121 "com.android.cts.verifier.bluetooth.BLE_ADD_SERVICE_FAIL"; 122 123 private static final UUID SERVICE_UUID = 124 UUID.fromString("00009999-0000-1000-8000-00805f9b34fb"); 125 private static final UUID CHARACTERISTIC_UUID = 126 UUID.fromString("00009998-0000-1000-8000-00805f9b34fb"); 127 private static final UUID CHARACTERISTIC_RESULT_UUID = 128 UUID.fromString("00009974-0000-1000-8000-00805f9b34fb"); 129 private static final UUID UPDATE_CHARACTERISTIC_UUID = 130 UUID.fromString("00009997-0000-1000-8000-00805f9b34fb"); 131 private static final UUID DESCRIPTOR_UUID = 132 UUID.fromString("00009996-0000-1000-8000-00805f9b34fb"); 133 public static final UUID ADV_SERVICE_UUID= 134 UUID.fromString("00003333-0000-1000-8000-00805f9b34fb"); 135 136 private static final UUID SERVICE_UUID_ADDITIONAL = 137 UUID.fromString("00009995-0000-1000-8000-00805f9b34fb"); 138 private static final UUID SERVICE_UUID_INCLUDED = 139 UUID.fromString("00009994-0000-1000-8000-00805f9b34fb"); 140 141 // Variable for registration permission of Characteristic 142 private static final UUID CHARACTERISTIC_NO_READ_UUID = 143 UUID.fromString("00009984-0000-1000-8000-00805f9b34fb"); 144 private static final UUID CHARACTERISTIC_NO_WRITE_UUID = 145 UUID.fromString("00009983-0000-1000-8000-00805f9b34fb"); 146 private static final UUID CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID = 147 UUID.fromString("00009982-0000-1000-8000-00805f9b34fb"); 148 private static final UUID CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID = 149 UUID.fromString("00009981-0000-1000-8000-00805f9b34fb"); 150 151 // Variable for registration permission of Descriptor 152 private static final UUID DESCRIPTOR_NO_READ_UUID = 153 UUID.fromString("00009973-0000-1000-8000-00805f9b34fb"); 154 private static final UUID DESCRIPTOR_NO_WRITE_UUID = 155 UUID.fromString("00009972-0000-1000-8000-00805f9b34fb"); 156 private static final UUID DESCRIPTOR_NEED_ENCRYPTED_READ_UUID = 157 UUID.fromString("00009969-0000-1000-8000-00805f9b34fb"); 158 private static final UUID DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID = 159 UUID.fromString("00009968-0000-1000-8000-00805f9b34fb"); 160 161 // Variable for registration upper limit confirmation of Characteristic 162 private static final UUID UPDATE_CHARACTERISTIC_UUID_1 = 163 UUID.fromString("00009989-0000-1000-8000-00805f9b34fb"); 164 private static final UUID UPDATE_CHARACTERISTIC_UUID_2 = 165 UUID.fromString("00009988-0000-1000-8000-00805f9b34fb"); 166 private static final UUID UPDATE_CHARACTERISTIC_UUID_3 = 167 UUID.fromString("00009987-0000-1000-8000-00805f9b34fb"); 168 private static final UUID UPDATE_CHARACTERISTIC_UUID_4 = 169 UUID.fromString("00009986-0000-1000-8000-00805f9b34fb"); 170 private static final UUID UPDATE_CHARACTERISTIC_UUID_5 = 171 UUID.fromString("00009985-0000-1000-8000-00805f9b34fb"); 172 private static final UUID UPDATE_CHARACTERISTIC_UUID_6 = 173 UUID.fromString("00009979-0000-1000-8000-00805f9b34fb"); 174 private static final UUID UPDATE_CHARACTERISTIC_UUID_7 = 175 UUID.fromString("00009978-0000-1000-8000-00805f9b34fb"); 176 private static final UUID UPDATE_CHARACTERISTIC_UUID_8 = 177 UUID.fromString("00009977-0000-1000-8000-00805f9b34fb"); 178 private static final UUID UPDATE_CHARACTERISTIC_UUID_9 = 179 UUID.fromString("00009976-0000-1000-8000-00805f9b34fb"); 180 private static final UUID UPDATE_CHARACTERISTIC_UUID_10 = 181 UUID.fromString("00009975-0000-1000-8000-00805f9b34fb"); 182 private static final UUID UPDATE_CHARACTERISTIC_UUID_11 = 183 UUID.fromString("00009959-0000-1000-8000-00805f9b34fb"); 184 private static final UUID UPDATE_CHARACTERISTIC_UUID_12 = 185 UUID.fromString("00009958-0000-1000-8000-00805f9b34fb"); 186 private static final UUID UPDATE_CHARACTERISTIC_UUID_13 = 187 UUID.fromString("00009957-0000-1000-8000-00805f9b34fb"); 188 private static final UUID UPDATE_CHARACTERISTIC_UUID_14 = 189 UUID.fromString("00009956-0000-1000-8000-00805f9b34fb"); 190 private static final UUID UPDATE_CHARACTERISTIC_UUID_15 = 191 UUID.fromString("00009955-0000-1000-8000-00805f9b34fb"); 192 193 private static final UUID UPDATE_DESCRIPTOR_UUID = 194 UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); 195 196 private static final UUID INDICATE_CHARACTERISTIC_UUID = 197 UUID.fromString("00009971-0000-1000-8000-00805f9b34fb"); 198 199 private static final int CONN_INTERVAL = 150; // connection interval 150ms 200 201 // Delay of notification when secure test failed to start. 202 private static final long NOTIFICATION_DELAY_OF_SECURE_TEST_FAILURE = 5 * 1000; 203 204 public static final String WRITE_VALUE = "SERVER_TEST"; 205 private static final String NOTIFY_VALUE = "NOTIFY_TEST"; 206 private static final String INDICATE_VALUE = "INDICATE_TEST"; 207 public static final String READ_NO_PERMISSION = "READ_NO_CHAR"; 208 public static final String WRITE_NO_PERMISSION = "WRITE_NO_CHAR"; 209 public static final String DESCRIPTOR_READ_NO_PERMISSION = "READ_NO_DESC"; 210 public static final String DESCRIPTOR_WRITE_NO_PERMISSION = "WRITE_NO_DESC"; 211 212 private BluetoothManager mBluetoothManager; 213 private BluetoothGattServer mGattServer; 214 private BluetoothGattService mService; 215 private BluetoothDevice mDevice; 216 private Timer mNotificationTimer; 217 private Handler mHandler; 218 private String mReliableWriteValue; 219 private BluetoothLeAdvertiser mAdvertiser; 220 private boolean mIndicated; 221 private int mNotifyCount; 222 private boolean mSecure; 223 private int mCountMtuChange; 224 private int mMtuSize = -1; 225 private String mMtuTestReceivedData; 226 private Runnable mResetValuesTask; 227 private BluetoothGattService mAdditionalNotificationService; 228 229 // Task to notify failure of starting secure test. 230 // Secure test calls BluetoothDevice#createBond() when devices were not paired. 231 // createBond() causes onConnectionStateChange() twice, and it works as strange sequence. 232 // At the first onConnectionStateChange(), target device is not paired(bond state is 233 // BluetoothDevice.BOND_NONE). 234 // At the second onConnectionStateChange(), target devices is paired(bond state is 235 // BluetoothDevice.BOND_BONDED). 236 // CTS Verifier will perform lazy check of bond state.Verifier checks bond state 237 // after NOTIFICATION_DELAY_OF_SECURE_TEST_FAILURE from the first onConnectionStateChange(). 238 private Runnable mNotificationTaskOfSecureTestStartFailure; 239 240 @Override onCreate()241 public void onCreate() { 242 super.onCreate(); 243 244 mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 245 mAdvertiser = mBluetoothManager.getAdapter().getBluetoothLeAdvertiser(); 246 mGattServer = mBluetoothManager.openGattServer(this, mCallbacks); 247 248 mService = createService(); 249 mAdditionalNotificationService = createAdditionalNotificationService(); 250 251 mDevice = null; 252 mReliableWriteValue = ""; 253 254 mHandler = new Handler(); 255 if (!mBluetoothManager.getAdapter().isEnabled()) { 256 notifyBluetoothDisabled(); 257 } else if (mGattServer == null) { 258 notifyOpenFail(); 259 } else if (mAdvertiser == null) { 260 notifyAdvertiseUnsupported(); 261 } else { 262 // start adding services 263 mNotifyCount = 11; 264 mSecure = false; 265 mCountMtuChange = 0; 266 if (!mGattServer.addService(mService)) { 267 notifyAddServiceFail(); 268 } 269 } 270 } 271 notifyBluetoothDisabled()272 private void notifyBluetoothDisabled() { 273 Intent intent = new Intent(BLE_BLUETOOTH_DISABLED); 274 sendBroadcast(intent); 275 } 276 notifyMismatchSecure()277 private void notifyMismatchSecure() { 278 Intent intent = new Intent(BLE_BLUETOOTH_MISMATCH_SECURE); 279 sendBroadcast(intent); 280 } 281 notifyMismatchInsecure()282 private void notifyMismatchInsecure() { 283 /* 284 Intent intent = new Intent(BLE_BLUETOOTH_MISMATCH_INSECURE); 285 sendBroadcast(intent); 286 */ 287 } 288 289 @Override onStartCommand(Intent intent, int flags, int startId)290 public int onStartCommand(Intent intent, int flags, int startId) { 291 String action = intent.getAction(); 292 if (action != null) { 293 switch (action) { 294 case BLE_ACTION_SERVER_SECURE: 295 mSecure = true; 296 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) { 297 showMessage("Skip MTU test."); 298 mCountMtuChange = 1; 299 notifyMtuRequest(); 300 mCountMtuChange = 2; 301 notifyMtuRequest(); 302 mCountMtuChange = 0; 303 } 304 break; 305 case BLE_ACTION_SERVER_NON_SECURE: 306 mSecure = false; 307 break; 308 } 309 } 310 311 if (mBluetoothManager.getAdapter().isEnabled() && (mAdvertiser != null)) { 312 startAdvertise(); 313 } 314 return START_NOT_STICKY; 315 } 316 317 @Override onBind(Intent intent)318 public IBinder onBind(Intent intent) { 319 return null; 320 } 321 322 @Override onDestroy()323 public void onDestroy() { 324 super.onDestroy(); 325 cancelNotificationTaskOfSecureTestStartFailure(); 326 stopAdvertise(); 327 if (mGattServer == null) { 328 return; 329 } 330 if (mDevice != null) { 331 mGattServer.cancelConnection(mDevice); 332 } 333 mGattServer.clearServices(); 334 mGattServer.close(); 335 } 336 337 /** 338 * Sets default value to characteristic and descriptor. 339 * 340 * Set operation will be done after connection interval. 341 * (If set values immediately, multiple read/write operations may fail.) 342 */ resetValues()343 private synchronized void resetValues() { 344 // cancel pending task 345 if (mResetValuesTask != null) { 346 mHandler.removeCallbacks(mResetValuesTask); 347 mResetValuesTask = null; 348 } 349 350 // reserve task 351 mResetValuesTask = new Runnable() { 352 @Override 353 public void run() { 354 getCharacteristic(CHARACTERISTIC_UUID).setValue(WRITE_VALUE.getBytes()); 355 getDescriptor().setValue(WRITE_VALUE.getBytes()); 356 } 357 }; 358 mHandler.postDelayed(mResetValuesTask, CONN_INTERVAL); 359 } 360 notifyOpenFail()361 private void notifyOpenFail() { 362 if (DEBUG) { 363 Log.d(TAG, "notifyOpenFail"); 364 } 365 Intent intent = new Intent(BLE_OPEN_FAIL); 366 sendBroadcast(intent); 367 } 368 notifyAddServiceFail()369 private void notifyAddServiceFail() { 370 if (DEBUG) { 371 Log.d(TAG, "notifyAddServiceFail"); 372 } 373 Intent intent = new Intent(BLE_ADD_SERVICE_FAIL); 374 sendBroadcast(intent); 375 } 376 notifyAdvertiseUnsupported()377 private void notifyAdvertiseUnsupported() { 378 if (DEBUG) { 379 Log.d(TAG, "notifyAdvertiseUnsupported"); 380 } 381 Intent intent = new Intent(BLE_ADVERTISE_UNSUPPORTED); 382 sendBroadcast(intent); 383 } 384 notifyConnected()385 private void notifyConnected() { 386 if (DEBUG) { 387 Log.d(TAG, "notifyConnected"); 388 } 389 Intent intent = new Intent(BLE_SERVER_CONNECTED); 390 sendBroadcast(intent); 391 392 resetValues(); 393 } 394 notifyDisconnected()395 private void notifyDisconnected() { 396 if (DEBUG) { 397 Log.d(TAG, "notifyDisconnected"); 398 } 399 Intent intent = new Intent(BLE_SERVER_DISCONNECTED); 400 sendBroadcast(intent); 401 } 402 notifyServiceAdded()403 private void notifyServiceAdded() { 404 if (DEBUG) { 405 Log.d(TAG, "notifyServiceAdded"); 406 } 407 Intent intent = new Intent(BLE_SERVICE_ADDED); 408 sendBroadcast(intent); 409 } 410 notifyMtuRequest()411 private void notifyMtuRequest() { 412 if (DEBUG) { 413 Log.d(TAG, "notifyMtuRequest"); 414 } 415 Intent intent; 416 if (mCountMtuChange == 1) { 417 intent = new Intent(BLE_MTU_REQUEST_23BYTES); 418 } else if (mCountMtuChange == 2) { 419 intent = new Intent(BLE_MTU_REQUEST_512BYTES); 420 } else { 421 return; // never occurs 422 } 423 sendBroadcast(intent); 424 } 425 notifyCharacteristicReadRequest(boolean resetValues)426 private void notifyCharacteristicReadRequest(boolean resetValues) { 427 if (DEBUG) { 428 Log.d(TAG, "notifyCharacteristicReadRequest"); 429 } 430 Intent intent = new Intent(BLE_CHARACTERISTIC_READ_REQUEST); 431 sendBroadcast(intent); 432 433 if (resetValues) { 434 resetValues(); 435 } 436 } 437 notifyCharacteristicWriteRequest()438 private void notifyCharacteristicWriteRequest() { 439 if (DEBUG) { 440 Log.d(TAG, "notifyCharacteristicWriteRequest"); 441 } 442 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_REQUEST); 443 sendBroadcast(intent); 444 445 resetValues(); 446 } 447 notifyCharacteristicReadRequestWithoutPermission()448 private void notifyCharacteristicReadRequestWithoutPermission() { 449 if (DEBUG) { 450 Log.d(TAG, "notifyCharacteristicReadRequestWithoutPermission"); 451 } 452 Intent intent = new Intent(BLE_CHARACTERISTIC_READ_REQUEST_WITHOUT_PERMISSION); 453 sendBroadcast(intent); 454 455 resetValues(); 456 } 457 notifyCharacteristicWriteRequestWithoutPermission()458 private void notifyCharacteristicWriteRequestWithoutPermission() { 459 if (DEBUG) { 460 Log.d(TAG, "notifyCharacteristicWriteRequestWithoutPermission"); 461 } 462 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_REQUEST_WITHOUT_PERMISSION); 463 sendBroadcast(intent); 464 465 resetValues(); 466 } 467 notifyCharacteristicReadRequestNeedEncrypted()468 private void notifyCharacteristicReadRequestNeedEncrypted() { 469 if (DEBUG) { 470 Log.d(TAG, "notifyCharacteristicReadRequestNeedEncrypted"); 471 } 472 Intent intent = new Intent(BLE_CHARACTERISTIC_READ_REQUEST_NEED_ENCRYPTED); 473 sendBroadcast(intent); 474 475 resetValues(); 476 } 477 notifyCharacteristicWriteRequestNeedEncrypted()478 private void notifyCharacteristicWriteRequestNeedEncrypted() { 479 if (DEBUG) { 480 Log.d(TAG, "notifyCharacteristicWriteRequestNeedEncrypted"); 481 } 482 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_REQUEST_NEED_ENCRYPTED); 483 sendBroadcast(intent); 484 485 resetValues(); 486 } 487 notifyCharacteristicNotificationRequest()488 private void notifyCharacteristicNotificationRequest() { 489 if (DEBUG) { 490 Log.d(TAG, "notifyCharacteristicNotificationRequest"); 491 } 492 mNotifyCount = 11; 493 Intent intent = new Intent(BLE_CHARACTERISTIC_NOTIFICATION_REQUEST); 494 sendBroadcast(intent); 495 496 resetValues(); 497 } 498 notifyCharacteristicIndicationRequest()499 private void notifyCharacteristicIndicationRequest() { 500 if (DEBUG) { 501 Log.d(TAG, "notifyCharacteristicIndicationRequest"); 502 } 503 Intent intent = new Intent(BLE_CHARACTERISTIC_INDICATE_REQUEST); 504 sendBroadcast(intent); 505 506 resetValues(); 507 } 508 notifyDescriptorReadRequest()509 private void notifyDescriptorReadRequest() { 510 if (DEBUG) { 511 Log.d(TAG, "notifyDescriptorReadRequest"); 512 } 513 Intent intent = new Intent(BLE_DESCRIPTOR_READ_REQUEST); 514 sendBroadcast(intent); 515 516 resetValues(); 517 } 518 notifyDescriptorWriteRequest()519 private void notifyDescriptorWriteRequest() { 520 if (DEBUG) { 521 Log.d(TAG, "notifyDescriptorWriteRequest"); 522 } 523 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_REQUEST); 524 sendBroadcast(intent); 525 526 resetValues(); 527 } 528 notifyDescriptorReadRequestWithoutPermission()529 private void notifyDescriptorReadRequestWithoutPermission() { 530 if (DEBUG) { 531 Log.d(TAG, "notifyDescriptorReadRequestWithoutPermission"); 532 } 533 Intent intent = new Intent(BLE_DESCRIPTOR_READ_REQUEST_WITHOUT_PERMISSION); 534 sendBroadcast(intent); 535 536 resetValues(); 537 } 538 notifyDescriptorWriteRequestWithoutPermission()539 private void notifyDescriptorWriteRequestWithoutPermission() { 540 if (DEBUG) { 541 Log.d(TAG, "notifyDescriptorWriteRequestWithoutPermission"); 542 } 543 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_REQUEST_WITHOUT_PERMISSION); 544 sendBroadcast(intent); 545 546 resetValues(); 547 } 548 notifyDescriptorReadRequestNeedEncrypted()549 private void notifyDescriptorReadRequestNeedEncrypted() { 550 if (DEBUG) { 551 Log.d(TAG, "notifyDescriptorReadRequestNeedEncrypted"); 552 } 553 Intent intent = new Intent(BLE_DESCRIPTOR_READ_REQUEST_NEED_ENCRYPTED); 554 sendBroadcast(intent); 555 556 resetValues(); 557 } 558 notifyDescriptorWriteRequestNeedEncrypted()559 private void notifyDescriptorWriteRequestNeedEncrypted() { 560 if (DEBUG) { 561 Log.d(TAG, "notifyDescriptorWriteRequestNeedEncrypted"); 562 } 563 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_REQUEST_NEED_ENCRYPTED); 564 sendBroadcast(intent); 565 566 resetValues(); 567 } 568 notifyExecuteWrite()569 private void notifyExecuteWrite() { 570 if (DEBUG) { 571 Log.d(TAG, "notifyExecuteWrite"); 572 } 573 Intent intent = new Intent(BLE_EXECUTE_WRITE); 574 sendBroadcast(intent); 575 576 resetValues(); 577 } 578 notifyReliableWriteBadResp()579 private void notifyReliableWriteBadResp() { 580 if (DEBUG) { 581 Log.d(TAG, "notifyReliableWriteBadResp"); 582 } 583 Intent intent = new Intent(BLE_RELIABLE_WRITE_BAD_RESP); 584 sendBroadcast(intent); 585 586 resetValues(); 587 } 588 getCharacteristic(UUID uuid)589 private BluetoothGattCharacteristic getCharacteristic(UUID uuid) { 590 BluetoothGattCharacteristic characteristic = mService.getCharacteristic(uuid); 591 if (characteristic == null) { 592 showMessage("Characteristic not found"); 593 } 594 return characteristic; 595 } 596 getDescriptor()597 private BluetoothGattDescriptor getDescriptor() { 598 BluetoothGattDescriptor descriptor = null; 599 600 BluetoothGattCharacteristic characteristic = getCharacteristic(CHARACTERISTIC_UUID); 601 if (characteristic != null) { 602 descriptor = characteristic.getDescriptor(DESCRIPTOR_UUID); 603 if (descriptor == null) { 604 showMessage("Descriptor not found"); 605 } 606 } 607 return descriptor; 608 } 609 610 /** 611 * Create service for notification test 612 * @return 613 */ createAdditionalNotificationService()614 private BluetoothGattService createAdditionalNotificationService() { 615 BluetoothGattService service = 616 new BluetoothGattService(SERVICE_UUID_ADDITIONAL, BluetoothGattService.SERVICE_TYPE_PRIMARY); 617 618 BluetoothGattCharacteristic notiCharacteristic = 619 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_1, 0x12, 0x1); 620 BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 621 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 622 notiCharacteristic.addDescriptor(descriptor); 623 notiCharacteristic.setValue(NOTIFY_VALUE); 624 service.addCharacteristic(notiCharacteristic); 625 626 notiCharacteristic = 627 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_2, 0x14, 0x11); 628 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 629 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 630 notiCharacteristic.addDescriptor(descriptor); 631 notiCharacteristic.setValue(NOTIFY_VALUE); 632 service.addCharacteristic(notiCharacteristic); 633 634 notiCharacteristic = 635 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_3, 0x16, 0x11); 636 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 637 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 638 notiCharacteristic.addDescriptor(descriptor); 639 notiCharacteristic.setValue(NOTIFY_VALUE); 640 service.addCharacteristic(notiCharacteristic); 641 642 notiCharacteristic = 643 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_4, 0x18, 0x10); 644 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 645 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 646 notiCharacteristic.addDescriptor(descriptor); 647 notiCharacteristic.setValue(NOTIFY_VALUE); 648 service.addCharacteristic(notiCharacteristic); 649 650 notiCharacteristic = 651 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_5, 0x1C, 0x11); 652 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 653 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 654 notiCharacteristic.addDescriptor(descriptor); 655 notiCharacteristic.setValue(NOTIFY_VALUE); 656 service.addCharacteristic(notiCharacteristic); 657 658 notiCharacteristic = 659 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_11, 0x3A, 0x11); 660 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 661 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 662 notiCharacteristic.addDescriptor(descriptor); 663 notiCharacteristic.setValue(NOTIFY_VALUE); 664 service.addCharacteristic(notiCharacteristic); 665 666 notiCharacteristic = 667 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_12, 0x3C, 0x11); 668 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 669 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 670 notiCharacteristic.addDescriptor(descriptor); 671 notiCharacteristic.setValue(NOTIFY_VALUE); 672 service.addCharacteristic(notiCharacteristic); 673 674 notiCharacteristic = 675 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_13, 0x3E, 0x11); 676 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 677 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 678 notiCharacteristic.addDescriptor(descriptor); 679 notiCharacteristic.setValue(NOTIFY_VALUE); 680 service.addCharacteristic(notiCharacteristic); 681 682 notiCharacteristic = 683 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_14, 0x10, 0x0); 684 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 685 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 686 notiCharacteristic.addDescriptor(descriptor); 687 notiCharacteristic.setValue(NOTIFY_VALUE); 688 service.addCharacteristic(notiCharacteristic); 689 690 notiCharacteristic = 691 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_15, 0x30, 0x0); 692 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 693 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 694 notiCharacteristic.addDescriptor(descriptor); 695 notiCharacteristic.setValue(NOTIFY_VALUE); 696 service.addCharacteristic(notiCharacteristic); 697 698 return service; 699 } 700 createService()701 private BluetoothGattService createService() { 702 BluetoothGattService service = 703 new BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY); 704 BluetoothGattCharacteristic characteristic = 705 new BluetoothGattCharacteristic(CHARACTERISTIC_UUID, 0x0A, 0x11); 706 characteristic.setValue(WRITE_VALUE.getBytes()); 707 708 BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(DESCRIPTOR_UUID, 0x11); 709 descriptor.setValue(WRITE_VALUE.getBytes()); 710 characteristic.addDescriptor(descriptor); 711 712 BluetoothGattDescriptor descriptor_permission = new BluetoothGattDescriptor(DESCRIPTOR_NO_READ_UUID, 0x10); 713 characteristic.addDescriptor(descriptor_permission); 714 715 descriptor_permission = new BluetoothGattDescriptor(DESCRIPTOR_NO_WRITE_UUID, 0x01); 716 characteristic.addDescriptor(descriptor_permission); 717 718 service.addCharacteristic(characteristic); 719 720 characteristic = 721 new BluetoothGattCharacteristic(CHARACTERISTIC_RESULT_UUID, 0x0A, 0x11); 722 723 BluetoothGattDescriptor descriptor_encrypted = new BluetoothGattDescriptor(DESCRIPTOR_NEED_ENCRYPTED_READ_UUID, 0x02); 724 characteristic.addDescriptor(descriptor_encrypted); 725 726 descriptor_encrypted = new BluetoothGattDescriptor(DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID, 0x20); 727 characteristic.addDescriptor(descriptor_encrypted); 728 729 service.addCharacteristic(characteristic); 730 731 // Add new Characteristics 732 // Registered the characteristic of read permission for operation confirmation. 733 characteristic = 734 new BluetoothGattCharacteristic(CHARACTERISTIC_NO_READ_UUID, 0x0A, 0x10); 735 service.addCharacteristic(characteristic); 736 737 // Registered the characteristic of write permission for operation confirmation. 738 characteristic = 739 new BluetoothGattCharacteristic(CHARACTERISTIC_NO_WRITE_UUID, 0x0A, 0x01); 740 service.addCharacteristic(characteristic); 741 742 // Registered the characteristic of authenticate (Encrypted) for operation confirmation. 743 characteristic = 744 new BluetoothGattCharacteristic(CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID, 0x0A, 0x02); 745 service.addCharacteristic(characteristic); 746 747 characteristic = 748 new BluetoothGattCharacteristic(CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID, 0x0A, 0x20); 749 service.addCharacteristic(characteristic); 750 751 // Add new Characteristics(Indicate) 752 BluetoothGattCharacteristic indicateCharacteristic = 753 new BluetoothGattCharacteristic(INDICATE_CHARACTERISTIC_UUID, 0x2A, 0x11); 754 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 755 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 756 indicateCharacteristic.addDescriptor(descriptor); 757 indicateCharacteristic.setValue(INDICATE_VALUE); 758 service.addCharacteristic(indicateCharacteristic); 759 760 // Add new Characteristics(Notify) 761 BluetoothGattCharacteristic notiCharacteristic = 762 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID, 0x1A, 0x11); 763 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 764 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 765 notiCharacteristic.addDescriptor(descriptor); 766 notiCharacteristic.setValue(NOTIFY_VALUE); 767 service.addCharacteristic(notiCharacteristic); 768 769 notiCharacteristic = 770 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_6, 0x1E, 0x11); 771 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 772 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 773 notiCharacteristic.addDescriptor(descriptor); 774 notiCharacteristic.setValue(NOTIFY_VALUE); 775 service.addCharacteristic(notiCharacteristic); 776 777 notiCharacteristic = 778 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_7, 0x32, 0x1); 779 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 780 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 781 notiCharacteristic.addDescriptor(descriptor); 782 notiCharacteristic.setValue(NOTIFY_VALUE); 783 service.addCharacteristic(notiCharacteristic); 784 785 notiCharacteristic = 786 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_8, 0x34, 0x11); 787 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 788 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 789 notiCharacteristic.addDescriptor(descriptor); 790 notiCharacteristic.setValue(NOTIFY_VALUE); 791 service.addCharacteristic(notiCharacteristic); 792 793 notiCharacteristic = 794 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_9, 0x36, 0x11); 795 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 796 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 797 notiCharacteristic.addDescriptor(descriptor); 798 notiCharacteristic.setValue(NOTIFY_VALUE); 799 service.addCharacteristic(notiCharacteristic); 800 801 notiCharacteristic = 802 new BluetoothGattCharacteristic(UPDATE_CHARACTERISTIC_UUID_10, 0x38, 0x10); 803 descriptor = new BluetoothGattDescriptor(UPDATE_DESCRIPTOR_UUID, 0x11); 804 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 805 notiCharacteristic.addDescriptor(descriptor); 806 notiCharacteristic.setValue(NOTIFY_VALUE); 807 service.addCharacteristic(notiCharacteristic); 808 809 return service; 810 } 811 showMessage(final String msg)812 private void showMessage(final String msg) { 813 mHandler.post(new Runnable() { 814 public void run() { 815 Toast.makeText(BleServerService.this, msg, Toast.LENGTH_SHORT).show(); 816 } 817 }); 818 } 819 onMtuTestDataReceive()820 private void onMtuTestDataReceive() { 821 822 Log.d(TAG, "onMtuTestDataReceive(" + mCountMtuChange + "):" + mMtuTestReceivedData); 823 824 // verify 825 if (mMtuTestReceivedData.equals(BleClientService.WRITE_VALUE_512BYTES_FOR_MTU)) { 826 827 // write back data 828 // MTU test verifies whether the write/read operations go well. 829 BluetoothGattCharacteristic characteristic = getCharacteristic(CHARACTERISTIC_UUID); 830 characteristic.setValue(mMtuTestReceivedData.getBytes()); 831 832 notifyMtuRequest(); 833 } else { 834 showMessage(getString(R.string.ble_mtu_fail_message)); 835 } 836 mMtuTestReceivedData = ""; 837 if (mCountMtuChange >= 2) { 838 // All MTU change tests completed 839 mCountMtuChange = 0; 840 } 841 } 842 cancelNotificationTaskOfSecureTestStartFailure()843 private synchronized void cancelNotificationTaskOfSecureTestStartFailure() { 844 if (mNotificationTaskOfSecureTestStartFailure != null) { 845 mHandler.removeCallbacks(mNotificationTaskOfSecureTestStartFailure); 846 mNotificationTaskOfSecureTestStartFailure = null; 847 } 848 } 849 850 private final BluetoothGattServerCallback mCallbacks = new BluetoothGattServerCallback() { 851 @Override 852 public void onConnectionStateChange(BluetoothDevice device, int status, int newState) { 853 if (DEBUG) { 854 Log.d(TAG, "onConnectionStateChange: newState=" + newState); 855 } 856 857 if (status == BluetoothGatt.GATT_SUCCESS) { 858 if (newState == BluetoothProfile.STATE_CONNECTED) { 859 mDevice = device; 860 boolean bonded = false; 861 Set<BluetoothDevice> pairedDevices = mBluetoothManager.getAdapter().getBondedDevices(); 862 if (pairedDevices.size() > 0) { 863 for (BluetoothDevice target : pairedDevices) { 864 if (target.getAddress().equals(device.getAddress())) { 865 bonded = true; 866 break; 867 } 868 } 869 } 870 871 if (mSecure && ((device.getBondState() == BluetoothDevice.BOND_NONE) || !bonded)) { 872 // not pairing and execute Secure Test 873 cancelNotificationTaskOfSecureTestStartFailure(); 874 /* 875 mNotificationTaskOfSecureTestStartFailure = new Runnable() { 876 @Override 877 public void run() { 878 mNotificationTaskOfSecureTestStartFailure = null; 879 if (mSecure && (mDevice.getBondState() != BluetoothDevice.BOND_BONDED)) { 880 notifyMismatchSecure(); 881 } 882 } 883 }; 884 mHandler.postDelayed(mNotificationTaskOfSecureTestStartFailure, 885 NOTIFICATION_DELAY_OF_SECURE_TEST_FAILURE); 886 */ 887 } else if (!mSecure && ((device.getBondState() != BluetoothDevice.BOND_NONE) || bonded)) { 888 // already pairing nad execute Insecure Test 889 /* 890 notifyMismatchInsecure(); 891 */ 892 } else { 893 cancelNotificationTaskOfSecureTestStartFailure(); 894 notifyConnected(); 895 } 896 } else if (status == BluetoothProfile.STATE_DISCONNECTED) { 897 notifyDisconnected(); 898 mDevice = null; 899 } 900 } 901 } 902 903 @Override 904 public void onServiceAdded(int status, BluetoothGattService service) { 905 if (DEBUG) { 906 Log.d(TAG, "onServiceAdded(): " + service.getUuid()); 907 dumpService(service, 0); 908 } 909 if (status == BluetoothGatt.GATT_SUCCESS) { 910 UUID uuid = service.getUuid(); 911 912 if (uuid.equals(mService.getUuid())) { 913 // create and add nested service 914 BluetoothGattService includedService = 915 new BluetoothGattService(SERVICE_UUID_INCLUDED, BluetoothGattService.SERVICE_TYPE_SECONDARY); 916 BluetoothGattCharacteristic characteristic = 917 new BluetoothGattCharacteristic(CHARACTERISTIC_UUID, 0x0A, 0x11); 918 characteristic.setValue(WRITE_VALUE.getBytes()); 919 BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(DESCRIPTOR_UUID, 0x11); 920 descriptor.setValue(WRITE_VALUE.getBytes()); 921 characteristic.addDescriptor(descriptor); 922 includedService.addCharacteristic(characteristic); 923 mGattServer.addService(includedService); 924 } else if (uuid.equals(SERVICE_UUID_INCLUDED)) { 925 mService.addService(service); 926 mGattServer.addService(mAdditionalNotificationService); 927 } else if (uuid.equals(mAdditionalNotificationService.getUuid())) { 928 // all services added 929 notifyServiceAdded(); 930 } else { 931 notifyAddServiceFail(); 932 } 933 } else { 934 notifyAddServiceFail(); 935 } 936 } 937 938 @Override 939 public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) { 940 if (mGattServer == null) { 941 if (DEBUG) { 942 Log.d(TAG, "GattServer is null, return"); 943 } 944 return; 945 } 946 if (DEBUG) { 947 Log.d(TAG, "onCharacteristicReadRequest()"); 948 } 949 950 boolean finished = false; 951 byte[] value = null; 952 if (mMtuSize > 0) { 953 byte[] buf = characteristic.getValue(); 954 if (buf != null) { 955 int len = Math.min((buf.length - offset), mMtuSize); 956 if (len > 0) { 957 value = Arrays.copyOfRange(buf, offset, (offset + len)); 958 } 959 finished = ((offset + len) >= buf.length); 960 if (finished) { 961 Log.d(TAG, "sent whole data: " + (new String(characteristic.getValue()))); 962 } 963 } 964 } else { 965 value = characteristic.getValue(); 966 finished = true; 967 } 968 969 mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value); 970 971 UUID uid = characteristic.getUuid(); 972 if (uid.equals(CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID)) { 973 notifyCharacteristicReadRequestNeedEncrypted(); 974 } else { 975 notifyCharacteristicReadRequest(finished); 976 } 977 } 978 979 @Override 980 public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, 981 BluetoothGattCharacteristic characteristic, 982 boolean preparedWrite, boolean responseNeeded, 983 int offset, byte[] value) { 984 if (mGattServer == null) { 985 if (DEBUG) { 986 Log.d(TAG, "GattServer is null, return"); 987 } 988 return; 989 } 990 if (DEBUG) { 991 Log.d(TAG, "onCharacteristicWriteRequest: preparedWrite=" + preparedWrite + ", responseNeeded= " + responseNeeded); 992 } 993 994 if (characteristic.getUuid().equals(CHARACTERISTIC_RESULT_UUID)) { 995 String resValue = new String(value); 996 Log.d(TAG, "CHARACTERISTIC_RESULT_UUID: resValue=" + resValue); 997 switch (resValue) { 998 case WRITE_NO_PERMISSION: 999 notifyCharacteristicWriteRequestWithoutPermission(); 1000 break; 1001 case READ_NO_PERMISSION: 1002 notifyCharacteristicReadRequestWithoutPermission(); 1003 break; 1004 case DESCRIPTOR_WRITE_NO_PERMISSION: 1005 notifyDescriptorWriteRequestWithoutPermission(); 1006 break; 1007 case DESCRIPTOR_READ_NO_PERMISSION: 1008 notifyDescriptorReadRequestWithoutPermission(); 1009 break; 1010 } 1011 if (responseNeeded) { 1012 mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value); 1013 } 1014 return; 1015 } 1016 1017 // MTU test flow 1018 if (mCountMtuChange > 0) { 1019 if (preparedWrite) { 1020 mMtuTestReceivedData += new String(value); 1021 } else { 1022 String strValue = new String(value); 1023 if (mCountMtuChange > 0) { 1024 mMtuTestReceivedData = strValue; 1025 onMtuTestDataReceive(); 1026 } 1027 } 1028 if (responseNeeded) { 1029 mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value); 1030 } 1031 1032 return; 1033 } 1034 1035 // Reliable write with bad response test flow 1036 String valueStr = new String(value); 1037 if (BleClientService.WRITE_VALUE_BAD_RESP.equals(valueStr)) { 1038 mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null); 1039 notifyReliableWriteBadResp(); 1040 return; 1041 } 1042 1043 if (preparedWrite) { 1044 mReliableWriteValue += (new String(value)); 1045 } else { 1046 characteristic.setValue(value); 1047 // verify 1048 if (Arrays.equals(BleClientService.WRITE_VALUE.getBytes(), characteristic.getValue())) { 1049 UUID uid = characteristic.getUuid(); 1050 if (uid.equals(CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID)) { 1051 notifyCharacteristicWriteRequestNeedEncrypted(); 1052 } else { 1053 notifyCharacteristicWriteRequest(); 1054 } 1055 } else { 1056 showMessage("Written data is not correct"); 1057 } 1058 } 1059 1060 if (responseNeeded) { 1061 mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value); 1062 } 1063 } 1064 1065 @Override 1066 public void onDescriptorReadRequest(BluetoothDevice device, int requestId, 1067 int offset, BluetoothGattDescriptor descriptor) { 1068 if (mGattServer == null) { 1069 if (DEBUG) { 1070 Log.d(TAG, "GattServer is null, return"); 1071 } 1072 return; 1073 } 1074 if (DEBUG) { 1075 Log.d(TAG, "onDescriptorReadRequest(): (descriptor == getDescriptor())=" 1076 + (descriptor == getDescriptor())); 1077 } 1078 1079 UUID uid = descriptor.getUuid(); 1080 if (uid.equals(DESCRIPTOR_NEED_ENCRYPTED_READ_UUID)){ 1081 notifyDescriptorReadRequestNeedEncrypted(); 1082 } else { 1083 notifyDescriptorReadRequest(); 1084 } 1085 1086 byte[] value = descriptor.getValue(); 1087 if (value == null) { 1088 throw new RuntimeException("descriptor data read is null"); 1089 } 1090 1091 mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value); 1092 } 1093 1094 @Override 1095 public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, 1096 BluetoothGattDescriptor descriptor, 1097 boolean preparedWrite, boolean responseNeeded, 1098 int offset, byte[] value) { 1099 if (mGattServer == null) { 1100 if (DEBUG) { 1101 Log.d(TAG, "GattServer is null, return"); 1102 } 1103 return; 1104 } 1105 BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic(); 1106 UUID uid = characteristic.getUuid(); 1107 if (DEBUG) { 1108 Log.d(TAG, "onDescriptorWriteRequest: preparedWrite=" + preparedWrite + ", responseNeeded= " + responseNeeded); 1109 Log.d(TAG, " characteristic uuid = " + uid); 1110 } 1111 1112 descriptor.setValue(value); 1113 UUID duid = descriptor.getUuid(); 1114 // If there is a written request to the CCCD for Notify. 1115 if (duid.equals(UPDATE_DESCRIPTOR_UUID)) { 1116 if (Arrays.equals(value, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)) { 1117 mGattServer.notifyCharacteristicChanged(mDevice, descriptor.getCharacteristic(), false); 1118 mIndicated = false; 1119 } else if (Arrays.equals(value, BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)) { 1120 mGattServer.notifyCharacteristicChanged(mDevice, descriptor.getCharacteristic(), true); 1121 mIndicated = true; 1122 } 1123 } else if (duid.equals(DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID)) { 1124 // verify 1125 if (Arrays.equals(BleClientService.WRITE_VALUE.getBytes(), descriptor.getValue())) { 1126 notifyDescriptorWriteRequestNeedEncrypted(); 1127 } else { 1128 showMessage("Written data is not correct"); 1129 } 1130 } else { 1131 // verify 1132 if (Arrays.equals(BleClientService.WRITE_VALUE.getBytes(), descriptor.getValue())) { 1133 notifyDescriptorWriteRequest(); 1134 } else { 1135 showMessage("Written data is not correct"); 1136 } 1137 } 1138 if (responseNeeded) { 1139 mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value); 1140 } 1141 } 1142 1143 @Override 1144 public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) { 1145 if (mGattServer == null) { 1146 if (DEBUG) { 1147 Log.d(TAG, "GattServer is null, return"); 1148 } 1149 return; 1150 } 1151 if (DEBUG) { 1152 Log.d(TAG, "onExecuteWrite"); 1153 } 1154 1155 if (execute) { 1156 if (mCountMtuChange > 0) { 1157 onMtuTestDataReceive(); 1158 } else { 1159 // verify 1160 String str = BleClientService.WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE 1161 + BleClientService.WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE; 1162 if (str.equals(mReliableWriteValue)) { 1163 notifyExecuteWrite(); 1164 } else { 1165 showMessage("Failed to receive data"); 1166 Log.d(TAG, "Failed to receive data:" + mReliableWriteValue); 1167 } 1168 } 1169 mReliableWriteValue = ""; 1170 } 1171 mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null); 1172 } 1173 1174 @Override 1175 public void onNotificationSent(BluetoothDevice device, int status) { 1176 if (mGattServer == null) { 1177 if (DEBUG) { 1178 Log.d(TAG, "GattServer is null, return"); 1179 } 1180 return; 1181 } 1182 if (DEBUG) { 1183 Log.d(TAG, "onNotificationSent"); 1184 } 1185 1186 if (status == BluetoothGatt.GATT_SUCCESS) { 1187 if (mIndicated) { 1188 notifyCharacteristicIndicationRequest(); 1189 } else { 1190 mNotifyCount--; 1191 if (mNotifyCount == 0) { 1192 notifyCharacteristicNotificationRequest(); 1193 } 1194 } 1195 } 1196 } 1197 1198 @Override 1199 public void onMtuChanged(BluetoothDevice device, int mtu) { 1200 if (mGattServer == null) { 1201 if (DEBUG) { 1202 Log.d(TAG, "GattServer is null, return"); 1203 } 1204 return; 1205 } 1206 if (DEBUG) { 1207 Log.d(TAG, "onMtuChanged"); 1208 } 1209 1210 mMtuSize = mtu; 1211 if (mCountMtuChange == 0) { 1212 if (mtu != 23) { 1213 String msg = String.format(getString(R.string.ble_mtu_mismatch_message), 1214 23, mtu); 1215 showMessage(msg); 1216 } 1217 } else if (mCountMtuChange == 1) { 1218 if (mtu != 512) { 1219 String msg = String.format(getString(R.string.ble_mtu_mismatch_message), 1220 512, mtu); 1221 showMessage(msg); 1222 } 1223 } 1224 mMtuTestReceivedData = ""; 1225 ++mCountMtuChange; 1226 } 1227 }; 1228 startAdvertise()1229 private void startAdvertise() { 1230 if (DEBUG) { 1231 Log.d(TAG, "startAdvertise"); 1232 } 1233 AdvertiseData data = new AdvertiseData.Builder() 1234 .addServiceData(new ParcelUuid(ADV_SERVICE_UUID), new byte[]{1,2,3}) 1235 .addServiceUuid(new ParcelUuid(ADV_SERVICE_UUID)) 1236 .build(); 1237 AdvertiseSettings setting = new AdvertiseSettings.Builder() 1238 .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) 1239 .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM) 1240 .setConnectable(true) 1241 .build(); 1242 mAdvertiser.startAdvertising(setting, data, mAdvertiseCallback); 1243 } 1244 stopAdvertise()1245 private void stopAdvertise() { 1246 if (DEBUG) { 1247 Log.d(TAG, "stopAdvertise"); 1248 } 1249 if (mAdvertiser != null) { 1250 mAdvertiser.stopAdvertising(mAdvertiseCallback); 1251 } 1252 } 1253 1254 private final AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback(){ 1255 @Override 1256 public void onStartFailure(int errorCode) { 1257 // Implementation for API Test. 1258 super.onStartFailure(errorCode); 1259 if (DEBUG) { 1260 Log.d(TAG, "onStartFailure"); 1261 } 1262 1263 if (errorCode == ADVERTISE_FAILED_FEATURE_UNSUPPORTED) { 1264 notifyAdvertiseUnsupported(); 1265 } else { 1266 notifyOpenFail(); 1267 } 1268 } 1269 1270 @Override 1271 public void onStartSuccess(AdvertiseSettings settingsInEffect) { 1272 // Implementation for API Test. 1273 super.onStartSuccess(settingsInEffect); 1274 if (DEBUG) { 1275 Log.d(TAG, "onStartSuccess"); 1276 } 1277 } 1278 }; 1279 dumpService(BluetoothGattService service, int level)1280 /*protected*/ static void dumpService(BluetoothGattService service, int level) { 1281 String indent = ""; 1282 for (int i = 0; i < level; ++i) { 1283 indent += " "; 1284 } 1285 1286 Log.d(TAG, indent + "[service]"); 1287 Log.d(TAG, indent + "UUID: " + service.getUuid()); 1288 Log.d(TAG, indent + " [characteristics]"); 1289 for (BluetoothGattCharacteristic ch : service.getCharacteristics()) { 1290 Log.d(TAG, indent + " UUID: " + ch.getUuid()); 1291 Log.d(TAG, indent + " properties: " + String.format("0x%02X", ch.getProperties())); 1292 Log.d(TAG, indent + " permissions: " + String.format("0x%02X", ch.getPermissions())); 1293 Log.d(TAG, indent + " [descriptors]"); 1294 for (BluetoothGattDescriptor d : ch.getDescriptors()) { 1295 Log.d(TAG, indent + " UUID: " + d.getUuid()); 1296 Log.d(TAG, indent + " permissions: " + String.format("0x%02X", d.getPermissions())); 1297 } 1298 } 1299 1300 if (service.getIncludedServices() != null) { 1301 Log.d(TAG, indent + " [included services]"); 1302 for (BluetoothGattService s : service.getIncludedServices()) { 1303 dumpService(s, level+1); 1304 } 1305 } 1306 } 1307 1308 } 1309 1310