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.BluetoothAdapter; 21 import android.bluetooth.BluetoothDevice; 22 import android.bluetooth.BluetoothGatt; 23 import android.bluetooth.BluetoothGattCallback; 24 import android.bluetooth.BluetoothGattCharacteristic; 25 import android.bluetooth.BluetoothGattDescriptor; 26 import android.bluetooth.BluetoothGattService; 27 import android.bluetooth.BluetoothManager; 28 import android.bluetooth.BluetoothProfile; 29 import android.bluetooth.le.BluetoothLeScanner; 30 import android.bluetooth.le.ScanCallback; 31 import android.bluetooth.le.ScanFilter; 32 import android.bluetooth.le.ScanResult; 33 import android.bluetooth.le.ScanSettings; 34 import android.content.BroadcastReceiver; 35 import android.content.Context; 36 import android.content.Intent; 37 import android.content.IntentFilter; 38 import android.os.Build; 39 import android.os.Handler; 40 import android.os.IBinder; 41 import android.os.ParcelUuid; 42 import android.text.TextUtils; 43 import android.util.Log; 44 import android.widget.Toast; 45 46 import com.android.cts.verifier.R; 47 48 import java.util.Arrays; 49 import java.util.List; 50 import java.util.Set; 51 import java.util.UUID; 52 53 public class BleClientService extends Service { 54 55 public static final boolean DEBUG = true; 56 public static final String TAG = "BleClientService"; 57 58 // Android N (2016 July 15, currently) BluetoothGatt#disconnect() does not work correct. 59 // (termination signal will not be sent) 60 // This flag switches to turn Bluetooth off instead of BluetoothGatt#disconnect(). 61 // If true, test will turn Bluetooth off. Otherwise, will call BluetoothGatt#disconnect(). 62 public static final boolean DISCONNECT_BY_TURN_BT_OFF_ON = (Build.VERSION.SDK_INT > Build.VERSION_CODES.M); 63 64 // for Version 1 test 65 // private static final int TRANSPORT_MODE_FOR_SECURE_CONNECTION = BluetoothDevice.TRANSPORT_AUTO; 66 // for Version 2 test 67 private static final int TRANSPORT_MODE_FOR_SECURE_CONNECTION = BluetoothDevice.TRANSPORT_LE; 68 69 public static final int COMMAND_CONNECT = 0; 70 public static final int COMMAND_DISCONNECT = 1; 71 public static final int COMMAND_DISCOVER_SERVICE = 2; 72 public static final int COMMAND_READ_RSSI = 3; 73 public static final int COMMAND_WRITE_CHARACTERISTIC = 4; 74 public static final int COMMAND_WRITE_CHARACTERISTIC_BAD_RESP = 5; 75 public static final int COMMAND_READ_CHARACTERISTIC = 6; 76 public static final int COMMAND_WRITE_DESCRIPTOR = 7; 77 public static final int COMMAND_READ_DESCRIPTOR = 8; 78 public static final int COMMAND_SET_NOTIFICATION = 9; 79 public static final int COMMAND_BEGIN_WRITE = 10; 80 public static final int COMMAND_EXECUTE_WRITE = 11; 81 public static final int COMMAND_ABORT_RELIABLE = 12; 82 public static final int COMMAND_SCAN_START = 13; 83 public static final int COMMAND_SCAN_STOP = 14; 84 85 public static final String BLE_BLUETOOTH_MISMATCH_SECURE = 86 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_MISMATCH_SECURE"; 87 public static final String BLE_BLUETOOTH_MISMATCH_INSECURE = 88 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_MISMATCH_INSECURE"; 89 public static final String BLE_BLUETOOTH_DISABLED = 90 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_DISABLED"; 91 public static final String BLE_BLUETOOTH_CONNECTED = 92 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_CONNECTED"; 93 public static final String BLE_BLUETOOTH_DISCONNECTED = 94 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_DISCONNECTED"; 95 public static final String BLE_SERVICES_DISCOVERED = 96 "com.android.cts.verifier.bluetooth.BLE_SERVICES_DISCOVERED"; 97 public static final String BLE_MTU_CHANGED_23BYTES = 98 "com.android.cts.verifier.bluetooth.BLE_MTU_CHANGED_23BYTES"; 99 public static final String BLE_MTU_CHANGED_512BYTES = 100 "com.android.cts.verifier.bluetooth.BLE_MTU_CHANGED_512BYTES"; 101 public static final String BLE_CHARACTERISTIC_READ = 102 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ"; 103 public static final String BLE_CHARACTERISTIC_WRITE = 104 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE"; 105 public static final String BLE_CHARACTERISTIC_CHANGED = 106 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_CHANGED"; 107 public static final String BLE_CHARACTERISTIC_INDICATED = 108 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_INDICATED"; 109 public static final String BLE_DESCRIPTOR_READ = 110 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ"; 111 public static final String BLE_DESCRIPTOR_WRITE = 112 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE"; 113 public static final String BLE_RELIABLE_WRITE_COMPLETED = 114 "com.android.cts.verifier.bluetooth.BLE_RELIABLE_WRITE_COMPLETED"; 115 public static final String BLE_RELIABLE_WRITE_BAD_RESP_COMPLETED = 116 "com.android.cts.verifier.bluetooth.BLE_RELIABLE_WRITE_BAD_RESP_COMPLETED"; 117 public static final String BLE_READ_REMOTE_RSSI = 118 "com.android.cts.verifier.bluetooth.BLE_READ_REMOTE_RSSI"; 119 public static final String BLE_CHARACTERISTIC_READ_NOPERMISSION = 120 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ_NOPERMISSION"; 121 public static final String BLE_CHARACTERISTIC_WRITE_NOPERMISSION = 122 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE_NOPERMISSION"; 123 public static final String BLE_DESCRIPTOR_READ_NOPERMISSION = 124 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ_NOPERMISSION"; 125 public static final String BLE_DESCRIPTOR_WRITE_NOPERMISSION = 126 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE_NOPERMISSION"; 127 public static final String BLE_CHARACTERISTIC_READ_NEED_ENCRYPTED = 128 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ_NEED_ENCRYPTED"; 129 public static final String BLE_CHARACTERISTIC_WRITE_NEED_ENCRYPTED = 130 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE_NEED_ENCRYPTED"; 131 public static final String BLE_DESCRIPTOR_READ_NEED_ENCRYPTED = 132 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ_NEED_ENCRYPTED"; 133 public static final String BLE_DESCRIPTOR_WRITE_NEED_ENCRYPTED = 134 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE_NEED_ENCRYPTED"; 135 public static final String BLE_CLIENT_ERROR = 136 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ERROR"; 137 138 public static final String EXTRA_COMMAND = 139 "com.android.cts.verifier.bluetooth.EXTRA_COMMAND"; 140 public static final String EXTRA_WRITE_VALUE = 141 "com.android.cts.verifier.bluetooth.EXTRA_WRITE_VALUE"; 142 public static final String EXTRA_BOOL = 143 "com.android.cts.verifier.bluetooth.EXTRA_BOOL"; 144 145 146 // Literal for Client Action 147 public static final String BLE_CLIENT_ACTION_CLIENT_CONNECT = 148 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_CLIENT_CONNECT"; 149 public static final String BLE_CLIENT_ACTION_CLIENT_CONNECT_SECURE = 150 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_CLIENT_CONNECT_SECURE"; 151 public static final String BLE_CLIENT_ACTION_BLE_DISCOVER_SERVICE = 152 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_BLE_DISCOVER_SERVICE"; 153 public static final String BLE_CLIENT_ACTION_REQUEST_MTU_23 = 154 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_REQUEST_MTU_23"; 155 public static final String BLE_CLIENT_ACTION_REQUEST_MTU_512 = 156 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_REQUEST_MTU_512"; 157 public static final String BLE_CLIENT_ACTION_READ_CHARACTERISTIC = 158 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_CHARACTERISTIC"; 159 public static final String BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC = 160 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC"; 161 public static final String BLE_CLIENT_ACTION_RELIABLE_WRITE = 162 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_RELIABLE_WRITE"; 163 public static final String BLE_CLIENT_ACTION_RELIABLE_WRITE_BAD_RESP = 164 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_RELIABLE_WRITE_BAD_RESP"; 165 public static final String BLE_CLIENT_ACTION_NOTIFY_CHARACTERISTIC = 166 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_NOTIFY_CHARACTERISTIC"; 167 public static final String BLE_CLIENT_ACTION_INDICATE_CHARACTERISTIC = 168 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_INDICATE_CHARACTERISTIC"; 169 public static final String BLE_CLIENT_ACTION_READ_DESCRIPTOR = 170 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_DESCRIPTOR"; 171 public static final String BLE_CLIENT_ACTION_WRITE_DESCRIPTOR = 172 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_WRITE_DESCRIPTOR"; 173 public static final String BLE_CLIENT_ACTION_READ_RSSI = 174 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_RSSI"; 175 public static final String BLE_CLIENT_ACTION_CLIENT_DISCONNECT = 176 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_CLIENT_DISCONNECT"; 177 public static final String BLE_CLIENT_ACTION_READ_CHARACTERISTIC_NO_PERMISSION = 178 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_CHARACTERISTIC_NO_PERMISSION"; 179 public static final String BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC_NO_PERMISSION = 180 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC_NO_PERMISSION"; 181 public static final String BLE_CLIENT_ACTION_READ_DESCRIPTOR_NO_PERMISSION = 182 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_DESCRIPTOR_NO_PERMISSION"; 183 public static final String BLE_CLIENT_ACTION_WRITE_DESCRIPTOR_NO_PERMISSION = 184 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_WRITE_DESCRIPTOR_NO_PERMISSION"; 185 public static final String BLE_CLIENT_ACTION_READ_AUTHENTICATED_CHARACTERISTIC = 186 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_AUTHENTICATED_CHARACTERISTIC"; 187 public static final String BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_CHARACTERISTIC = 188 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_CHARACTERISTIC"; 189 public static final String BLE_CLIENT_ACTION_READ_AUTHENTICATED_DESCRIPTOR = 190 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_AUTHENTICATED_DESCRIPTOR"; 191 public static final String BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_DESCRIPTOR = 192 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_DESCRIPTOR"; 193 194 public static final String EXTRA_CHARACTERISTIC_VALUE = 195 "com.android.cts.verifier.bluetooth.EXTRA_CHARACTERISTIC_VALUE"; 196 public static final String EXTRA_DESCRIPTOR_VALUE = 197 "com.android.cts.verifier.bluetooth.EXTRA_DESCRIPTOR_VALUE"; 198 public static final String EXTRA_RSSI_VALUE = 199 "com.android.cts.verifier.bluetooth.EXTRA_RSSI_VALUE"; 200 public static final String EXTRA_ERROR_MESSAGE = 201 "com.android.cts.verifier.bluetooth.EXTRA_ERROR_MESSAGE"; 202 203 public static final String WRITE_VALUE_512BYTES_FOR_MTU = createTestData(512); 204 public static final String WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE = createTestData(507); 205 206 private static final UUID SERVICE_UUID = 207 UUID.fromString("00009999-0000-1000-8000-00805f9b34fb"); 208 private static final UUID CHARACTERISTIC_UUID = 209 UUID.fromString("00009998-0000-1000-8000-00805f9b34fb"); 210 private static final UUID CHARACTERISTIC_RESULT_UUID = 211 UUID.fromString("00009974-0000-1000-8000-00805f9b34fb"); 212 private static final UUID UPDATE_CHARACTERISTIC_UUID = 213 UUID.fromString("00009997-0000-1000-8000-00805f9b34fb"); 214 private static final UUID DESCRIPTOR_UUID = 215 UUID.fromString("00009996-0000-1000-8000-00805f9b34fb"); 216 217 private static final UUID SERVICE_UUID_ADDITIONAL = 218 UUID.fromString("00009995-0000-1000-8000-00805f9b34fb"); 219 220 // Literal for registration permission of Characteristic 221 private static final UUID CHARACTERISTIC_NO_READ_UUID = 222 UUID.fromString("00009984-0000-1000-8000-00805f9b34fb"); 223 private static final UUID CHARACTERISTIC_NO_WRITE_UUID = 224 UUID.fromString("00009983-0000-1000-8000-00805f9b34fb"); 225 private static final UUID CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID = 226 UUID.fromString("00009982-0000-1000-8000-00805f9b34fb"); 227 private static final UUID CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID = 228 UUID.fromString("00009981-0000-1000-8000-00805f9b34fb"); 229 230 // Literal for registration permission of Descriptor 231 private static final UUID DESCRIPTOR_NO_READ_UUID = 232 UUID.fromString("00009973-0000-1000-8000-00805f9b34fb"); 233 private static final UUID DESCRIPTOR_NO_WRITE_UUID = 234 UUID.fromString("00009972-0000-1000-8000-00805f9b34fb"); 235 private static final UUID DESCRIPTOR_NEED_ENCRYPTED_READ_UUID = 236 UUID.fromString("00009969-0000-1000-8000-00805f9b34fb"); 237 private static final UUID DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID = 238 UUID.fromString("00009968-0000-1000-8000-00805f9b34fb"); 239 240 // Literal for registration upper limit confirmation of Characteristic 241 private static final UUID UPDATE_CHARACTERISTIC_UUID_1 = 242 UUID.fromString("00009989-0000-1000-8000-00805f9b34fb"); 243 private static final UUID UPDATE_CHARACTERISTIC_UUID_2 = 244 UUID.fromString("00009988-0000-1000-8000-00805f9b34fb"); 245 private static final UUID UPDATE_CHARACTERISTIC_UUID_3 = 246 UUID.fromString("00009987-0000-1000-8000-00805f9b34fb"); 247 private static final UUID UPDATE_CHARACTERISTIC_UUID_4 = 248 UUID.fromString("00009986-0000-1000-8000-00805f9b34fb"); 249 private static final UUID UPDATE_CHARACTERISTIC_UUID_5 = 250 UUID.fromString("00009985-0000-1000-8000-00805f9b34fb"); 251 private static final UUID UPDATE_CHARACTERISTIC_UUID_6 = 252 UUID.fromString("00009979-0000-1000-8000-00805f9b34fb"); 253 private static final UUID UPDATE_CHARACTERISTIC_UUID_7 = 254 UUID.fromString("00009978-0000-1000-8000-00805f9b34fb"); 255 private static final UUID UPDATE_CHARACTERISTIC_UUID_8 = 256 UUID.fromString("00009977-0000-1000-8000-00805f9b34fb"); 257 private static final UUID UPDATE_CHARACTERISTIC_UUID_9 = 258 UUID.fromString("00009976-0000-1000-8000-00805f9b34fb"); 259 private static final UUID UPDATE_CHARACTERISTIC_UUID_10 = 260 UUID.fromString("00009975-0000-1000-8000-00805f9b34fb"); 261 private static final UUID UPDATE_CHARACTERISTIC_UUID_11 = 262 UUID.fromString("00009959-0000-1000-8000-00805f9b34fb"); 263 private static final UUID UPDATE_CHARACTERISTIC_UUID_12 = 264 UUID.fromString("00009958-0000-1000-8000-00805f9b34fb"); 265 private static final UUID UPDATE_CHARACTERISTIC_UUID_13 = 266 UUID.fromString("00009957-0000-1000-8000-00805f9b34fb"); 267 private static final UUID UPDATE_CHARACTERISTIC_UUID_14 = 268 UUID.fromString("00009956-0000-1000-8000-00805f9b34fb"); 269 private static final UUID UPDATE_CHARACTERISTIC_UUID_15 = 270 UUID.fromString("00009955-0000-1000-8000-00805f9b34fb"); 271 272 private static final UUID UPDATE_DESCRIPTOR_UUID = 273 UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); 274 275 private static final UUID INDICATE_CHARACTERISTIC_UUID = 276 UUID.fromString("00009971-0000-1000-8000-00805f9b34fb"); 277 278 public static final String WRITE_VALUE = "CLIENT_TEST"; 279 private static final String NOTIFY_VALUE = "NOTIFY_TEST"; 280 public static final String WRITE_VALUE_BAD_RESP = "BAD_RESP_TEST"; 281 282 // current test category 283 private String mCurrentAction; 284 285 private BluetoothManager mBluetoothManager; 286 private BluetoothAdapter mBluetoothAdapter; 287 private BluetoothDevice mDevice; 288 private BluetoothGatt mBluetoothGatt; 289 private BluetoothLeScanner mScanner; 290 private Handler mHandler; 291 private Context mContext; 292 private boolean mSecure; 293 private int mNotifyCount; 294 private boolean mValidityService; 295 private ReliableWriteState mExecReliableWrite; 296 private byte[] mBuffer; 297 298 // Handler for communicating task with peer. 299 private TestTaskQueue mTaskQueue; 300 301 // Lock for synchronization during notification request test. 302 private final Object mRequestNotificationLock = new Object(); 303 304 private enum ReliableWriteState { 305 RELIABLE_WRITE_NONE, 306 RELIABLE_WRITE_WRITE_1ST_DATA, 307 RELIABLE_WRITE_WRITE_2ND_DATA, 308 RELIABLE_WRITE_EXECUTE, 309 RELIABLE_WRITE_BAD_RESP 310 } 311 312 @Override onCreate()313 public void onCreate() { 314 super.onCreate(); 315 316 registerReceiver(mBondStatusReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED)); 317 318 mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 319 mBluetoothAdapter = mBluetoothManager.getAdapter(); 320 mScanner = mBluetoothAdapter.getBluetoothLeScanner(); 321 mHandler = new Handler(); 322 mContext = this; 323 mNotifyCount = 0; 324 325 mTaskQueue = new TestTaskQueue(getClass().getName() + "_taskHandlerThread"); 326 } 327 328 @Override onStartCommand(final Intent intent, int flags, int startId)329 public int onStartCommand(final Intent intent, int flags, int startId) { 330 if (!mBluetoothAdapter.isEnabled()) { 331 notifyBluetoothDisabled(); 332 } else { 333 mTaskQueue.addTask(new Runnable() { 334 @Override 335 public void run() { 336 onTestFinish(intent.getAction()); 337 } 338 }, 1500); 339 } 340 return START_NOT_STICKY; 341 } 342 onTestFinish(String action)343 private void onTestFinish(String action) { 344 mCurrentAction = action; 345 if (mCurrentAction != null) { 346 switch (mCurrentAction) { 347 case BLE_CLIENT_ACTION_CLIENT_CONNECT_SECURE: 348 mSecure = true; 349 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 350 startScan(); 351 break; 352 case BLE_CLIENT_ACTION_CLIENT_CONNECT: 353 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 354 startScan(); 355 break; 356 case BLE_CLIENT_ACTION_BLE_DISCOVER_SERVICE: 357 if (mBluetoothGatt != null && mBleState == BluetoothProfile.STATE_CONNECTED) { 358 mBluetoothGatt.discoverServices(); 359 } else { 360 showMessage("Bluetooth LE not cnnected."); 361 } 362 break; 363 case BLE_CLIENT_ACTION_REQUEST_MTU_23: 364 case BLE_CLIENT_ACTION_REQUEST_MTU_512: // fall through 365 requestMtu(); 366 break; 367 case BLE_CLIENT_ACTION_READ_CHARACTERISTIC: 368 readCharacteristic(CHARACTERISTIC_UUID); 369 break; 370 case BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC: 371 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE); 372 break; 373 case BLE_CLIENT_ACTION_RELIABLE_WRITE: 374 case BLE_CLIENT_ACTION_RELIABLE_WRITE_BAD_RESP: // fall through 375 mTaskQueue.addTask(new Runnable() { 376 @Override 377 public void run() { 378 reliableWrite(); 379 } 380 }); 381 break; 382 case BLE_CLIENT_ACTION_INDICATE_CHARACTERISTIC: 383 setNotification(INDICATE_CHARACTERISTIC_UUID, true); 384 break; 385 case BLE_CLIENT_ACTION_NOTIFY_CHARACTERISTIC: 386 // Registered the notify to characteristics in the service 387 mTaskQueue.addTask(new Runnable() { 388 @Override 389 public void run() { 390 mNotifyCount = 16; 391 setNotification(UPDATE_CHARACTERISTIC_UUID, true); 392 waitForDisableNotificationCompletion(); 393 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_1, true); 394 waitForDisableNotificationCompletion(); 395 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_2, true); 396 waitForDisableNotificationCompletion(); 397 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_3, true); 398 waitForDisableNotificationCompletion(); 399 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_4, true); 400 waitForDisableNotificationCompletion(); 401 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_5, true); 402 waitForDisableNotificationCompletion(); 403 setNotification(UPDATE_CHARACTERISTIC_UUID_6, true); 404 waitForDisableNotificationCompletion(); 405 setNotification(UPDATE_CHARACTERISTIC_UUID_7, true); 406 waitForDisableNotificationCompletion(); 407 setNotification(UPDATE_CHARACTERISTIC_UUID_8, true); 408 waitForDisableNotificationCompletion(); 409 setNotification(UPDATE_CHARACTERISTIC_UUID_9, true); 410 waitForDisableNotificationCompletion(); 411 setNotification(UPDATE_CHARACTERISTIC_UUID_10, true); 412 waitForDisableNotificationCompletion(); 413 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_11, true); 414 waitForDisableNotificationCompletion(); 415 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_12, true); 416 waitForDisableNotificationCompletion(); 417 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_13, true); 418 waitForDisableNotificationCompletion(); 419 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_14, true); 420 waitForDisableNotificationCompletion(); 421 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_15, true); 422 waitForDisableNotificationCompletion(); 423 } 424 }); 425 break; 426 case BLE_CLIENT_ACTION_READ_DESCRIPTOR: 427 readDescriptor(DESCRIPTOR_UUID); 428 break; 429 case BLE_CLIENT_ACTION_WRITE_DESCRIPTOR: 430 writeDescriptor(DESCRIPTOR_UUID, WRITE_VALUE); 431 break; 432 case BLE_CLIENT_ACTION_READ_RSSI: 433 if (mBluetoothGatt != null) { 434 mBluetoothGatt.readRemoteRssi(); 435 } 436 break; 437 case BLE_CLIENT_ACTION_CLIENT_DISCONNECT: 438 if (mBluetoothGatt != null) { 439 mBluetoothGatt.disconnect(); 440 } 441 break; 442 case BLE_CLIENT_ACTION_READ_CHARACTERISTIC_NO_PERMISSION: 443 readCharacteristic(CHARACTERISTIC_NO_READ_UUID); 444 break; 445 case BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC_NO_PERMISSION: 446 writeCharacteristic(CHARACTERISTIC_NO_WRITE_UUID, WRITE_VALUE); 447 break; 448 case BLE_CLIENT_ACTION_READ_DESCRIPTOR_NO_PERMISSION: 449 readDescriptor(DESCRIPTOR_NO_READ_UUID); 450 break; 451 case BLE_CLIENT_ACTION_WRITE_DESCRIPTOR_NO_PERMISSION: 452 writeDescriptor(DESCRIPTOR_NO_WRITE_UUID, WRITE_VALUE); 453 break; 454 case BLE_CLIENT_ACTION_READ_AUTHENTICATED_CHARACTERISTIC: 455 readCharacteristic(CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID); 456 break; 457 case BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_CHARACTERISTIC: 458 writeCharacteristic(CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID, WRITE_VALUE); 459 break; 460 case BLE_CLIENT_ACTION_READ_AUTHENTICATED_DESCRIPTOR: 461 readDescriptor(CHARACTERISTIC_RESULT_UUID, DESCRIPTOR_NEED_ENCRYPTED_READ_UUID); 462 break; 463 case BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_DESCRIPTOR: 464 writeDescriptor(CHARACTERISTIC_RESULT_UUID, DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID, WRITE_VALUE); 465 break; 466 } 467 } 468 } 469 470 @Override onBind(Intent intent)471 public IBinder onBind(Intent intent) { 472 return null; 473 } 474 475 @Override onDestroy()476 public void onDestroy() { 477 super.onDestroy(); 478 if (mBluetoothGatt != null) { 479 mBluetoothGatt.disconnect(); 480 mBluetoothGatt.close(); 481 mBluetoothGatt = null; 482 } 483 stopScan(); 484 unregisterReceiver(mBondStatusReceiver); 485 486 mTaskQueue.quit(); 487 } 488 connectGatt(BluetoothDevice device, Context context, boolean autoConnect, boolean isSecure, BluetoothGattCallback callback)489 public static BluetoothGatt connectGatt(BluetoothDevice device, Context context, boolean autoConnect, boolean isSecure, BluetoothGattCallback callback) { 490 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 491 if (isSecure) { 492 if (TRANSPORT_MODE_FOR_SECURE_CONNECTION == BluetoothDevice.TRANSPORT_AUTO) { 493 Toast.makeText(context, "connectGatt(transport=AUTO)", Toast.LENGTH_SHORT).show(); 494 } else { 495 Toast.makeText(context, "connectGatt(transport=LE)", Toast.LENGTH_SHORT).show(); 496 } 497 return device.connectGatt(context, autoConnect, callback, TRANSPORT_MODE_FOR_SECURE_CONNECTION); 498 } else { 499 Toast.makeText(context, "connectGatt(transport=LE)", Toast.LENGTH_SHORT).show(); 500 return device.connectGatt(context, autoConnect, callback, BluetoothDevice.TRANSPORT_LE); 501 } 502 } else { 503 Toast.makeText(context, "connectGatt", Toast.LENGTH_SHORT).show(); 504 return device.connectGatt(context, autoConnect, callback); 505 } 506 } 507 requestMtu()508 private void requestMtu() { 509 if (mBluetoothGatt != null) { 510 // MTU request test does not work on Android 6.0 in secure mode. 511 // (BluetoothDevice#createBond() does not work on Android 6.0. 512 // So devices can't establish Bluetooth LE pairing.) 513 boolean mtuTestExecutable = true; 514 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) { 515 mtuTestExecutable = !mSecure; 516 } 517 518 if (mtuTestExecutable) { 519 int mtu = 0; 520 if (BLE_CLIENT_ACTION_REQUEST_MTU_23.equals(mCurrentAction)) { 521 mtu = 23; 522 } else if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction)) { 523 mtu = 512; 524 } else { 525 throw new IllegalStateException("unexpected action: " + mCurrentAction); 526 } 527 mBluetoothGatt.requestMtu(mtu); 528 } else { 529 showMessage("Skip MTU test."); 530 notifyMtuChanged(); 531 } 532 } 533 } 534 writeCharacteristic(BluetoothGattCharacteristic characteristic, String writeValue)535 private void writeCharacteristic(BluetoothGattCharacteristic characteristic, String writeValue) { 536 if (characteristic != null) { 537 characteristic.setValue(writeValue); 538 mBluetoothGatt.writeCharacteristic(characteristic); 539 } 540 } 541 writeCharacteristic(UUID uid, String writeValue)542 private void writeCharacteristic(UUID uid, String writeValue) { 543 BluetoothGattCharacteristic characteristic = getCharacteristic(uid); 544 if (characteristic != null){ 545 writeCharacteristic(characteristic, writeValue); 546 } 547 } 548 readCharacteristic(UUID uuid)549 private void readCharacteristic(UUID uuid) { 550 BluetoothGattCharacteristic characteristic = getCharacteristic(uuid); 551 if (characteristic != null) { 552 mBluetoothGatt.readCharacteristic(characteristic); 553 } 554 } 555 writeDescriptor(UUID uid, String writeValue)556 private void writeDescriptor(UUID uid, String writeValue) { 557 BluetoothGattDescriptor descriptor = getDescriptor(uid); 558 if (descriptor != null) { 559 descriptor.setValue(writeValue.getBytes()); 560 mBluetoothGatt.writeDescriptor(descriptor); 561 } 562 } 563 readDescriptor(UUID uuid)564 private void readDescriptor(UUID uuid) { 565 BluetoothGattDescriptor descriptor = getDescriptor(uuid); 566 if (descriptor != null) { 567 mBluetoothGatt.readDescriptor(descriptor); 568 } 569 } 570 writeDescriptor(UUID cuid, UUID duid, String writeValue)571 private void writeDescriptor(UUID cuid, UUID duid, String writeValue) { 572 BluetoothGattDescriptor descriptor = getDescriptor(cuid, duid); 573 if (descriptor != null) { 574 descriptor.setValue(writeValue.getBytes()); 575 mBluetoothGatt.writeDescriptor(descriptor); 576 } 577 } 578 readDescriptor(UUID cuid, UUID duid)579 private void readDescriptor(UUID cuid, UUID duid) { 580 BluetoothGattDescriptor descriptor = getDescriptor(cuid, duid); 581 if (descriptor != null) { 582 mBluetoothGatt.readDescriptor(descriptor); 583 } 584 } 585 notifyDisableNotificationCompletion()586 private void notifyDisableNotificationCompletion() { 587 synchronized (mRequestNotificationLock) { 588 mRequestNotificationLock.notify(); 589 } 590 } 591 waitForDisableNotificationCompletion()592 private void waitForDisableNotificationCompletion() { 593 synchronized (mRequestNotificationLock) { 594 try { 595 mRequestNotificationLock.wait(); 596 } catch (InterruptedException e) { 597 Log.e(TAG, "Error in waitForDisableNotificationCompletion" + e); 598 } 599 } 600 } 601 setNotification(BluetoothGattCharacteristic characteristic, boolean enable)602 private void setNotification(BluetoothGattCharacteristic characteristic, boolean enable) { 603 if (characteristic != null) { 604 mBluetoothGatt.setCharacteristicNotification(characteristic, enable); 605 BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UPDATE_DESCRIPTOR_UUID); 606 if (enable) { 607 if (characteristic.getUuid().equals(INDICATE_CHARACTERISTIC_UUID)) { 608 descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE); 609 } else { 610 descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); 611 } 612 } else { 613 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 614 } 615 mBluetoothGatt.writeDescriptor(descriptor); 616 } 617 } 618 setNotification(UUID serviceUid, UUID characteristicUid, boolean enable)619 private void setNotification(UUID serviceUid, UUID characteristicUid, boolean enable) { 620 BluetoothGattCharacteristic characteristic = getCharacteristic(serviceUid, characteristicUid); 621 if (characteristic != null) { 622 setNotification(characteristic, enable); 623 } 624 } 625 setNotification(UUID uid, boolean enable)626 private void setNotification(UUID uid, boolean enable) { 627 BluetoothGattCharacteristic characteristic = getCharacteristic(uid); 628 if (characteristic != null) { 629 setNotification(characteristic, enable); 630 } 631 } 632 notifyError(String message)633 private void notifyError(String message) { 634 showMessage(message); 635 Log.i(TAG, message); 636 637 Intent intent = new Intent(BLE_CLIENT_ERROR); 638 sendBroadcast(intent); 639 } 640 notifyMismatchSecure()641 private void notifyMismatchSecure() { 642 Intent intent = new Intent(BLE_BLUETOOTH_MISMATCH_SECURE); 643 sendBroadcast(intent); 644 } 645 notifyMismatchInsecure()646 private void notifyMismatchInsecure() { 647 Intent intent = new Intent(BLE_BLUETOOTH_MISMATCH_INSECURE); 648 sendBroadcast(intent); 649 } 650 notifyBluetoothDisabled()651 private void notifyBluetoothDisabled() { 652 Intent intent = new Intent(BLE_BLUETOOTH_DISABLED); 653 sendBroadcast(intent); 654 } 655 notifyConnected()656 private void notifyConnected() { 657 showMessage("Bluetooth LE connected"); 658 Intent intent = new Intent(BLE_BLUETOOTH_CONNECTED); 659 sendBroadcast(intent); 660 } 661 notifyDisconnected()662 private void notifyDisconnected() { 663 showMessage("Bluetooth LE disconnected"); 664 Intent intent = new Intent(BLE_BLUETOOTH_DISCONNECTED); 665 sendBroadcast(intent); 666 } 667 notifyServicesDiscovered()668 private void notifyServicesDiscovered() { 669 showMessage("Service discovered"); 670 Intent intent = new Intent(BLE_SERVICES_DISCOVERED); 671 sendBroadcast(intent); 672 } 673 notifyMtuChanged()674 private void notifyMtuChanged() { 675 Intent intent; 676 if (BLE_CLIENT_ACTION_REQUEST_MTU_23.equals(mCurrentAction)) { 677 intent = new Intent(BLE_MTU_CHANGED_23BYTES); 678 } else if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction)) { 679 intent = new Intent(BLE_MTU_CHANGED_512BYTES); 680 } else { 681 throw new IllegalStateException("unexpected action: " + mCurrentAction); 682 } 683 sendBroadcast(intent); 684 } 685 notifyCharacteristicRead(String value)686 private void notifyCharacteristicRead(String value) { 687 showMessage("Characteristic read: " + value); 688 Intent intent = new Intent(BLE_CHARACTERISTIC_READ); 689 intent.putExtra(EXTRA_CHARACTERISTIC_VALUE, value); 690 sendBroadcast(intent); 691 } 692 notifyCharacteristicWrite(String value)693 private void notifyCharacteristicWrite(String value) { 694 showMessage("Characteristic write: " + value); 695 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE); 696 sendBroadcast(intent); 697 } 698 notifyCharacteristicReadNoPermission()699 private void notifyCharacteristicReadNoPermission() { 700 showMessage("Characteristic not read: No Permission"); 701 Intent intent = new Intent(BLE_CHARACTERISTIC_READ_NOPERMISSION); 702 sendBroadcast(intent); 703 } 704 notifyCharacteristicWriteNoPermission(String value)705 private void notifyCharacteristicWriteNoPermission(String value) { 706 showMessage("Characteristic write: No Permission"); 707 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_NOPERMISSION); 708 sendBroadcast(intent); 709 } 710 notifyCharacteristicReadNeedEncrypted(String value)711 private void notifyCharacteristicReadNeedEncrypted(String value) { 712 showMessage("Characteristic read with encrypted: " + value); 713 Intent intent = new Intent(BLE_CHARACTERISTIC_READ_NEED_ENCRYPTED); 714 sendBroadcast(intent); 715 } 716 notifyCharacteristicWriteNeedEncrypted(String value)717 private void notifyCharacteristicWriteNeedEncrypted(String value) { 718 showMessage("Characteristic write with encrypted: " + value); 719 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_NEED_ENCRYPTED); 720 sendBroadcast(intent); 721 } 722 notifyCharacteristicChanged()723 private void notifyCharacteristicChanged() { 724 showMessage("Characteristic changed"); 725 Intent intent = new Intent(BLE_CHARACTERISTIC_CHANGED); 726 sendBroadcast(intent); 727 } 728 notifyCharacteristicIndicated()729 private void notifyCharacteristicIndicated() { 730 showMessage("Characteristic Indicated"); 731 Intent intent = new Intent(BLE_CHARACTERISTIC_INDICATED); 732 sendBroadcast(intent); 733 } 734 notifyDescriptorRead(String value)735 private void notifyDescriptorRead(String value) { 736 showMessage("Descriptor read: " + value); 737 Intent intent = new Intent(BLE_DESCRIPTOR_READ); 738 intent.putExtra(EXTRA_DESCRIPTOR_VALUE, value); 739 sendBroadcast(intent); 740 } 741 notifyDescriptorWrite(String value)742 private void notifyDescriptorWrite(String value) { 743 showMessage("Descriptor write: " + value); 744 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE); 745 sendBroadcast(intent); 746 } 747 notifyDescriptorReadNoPermission()748 private void notifyDescriptorReadNoPermission() { 749 showMessage("Descriptor read: No Permission"); 750 Intent intent = new Intent(BLE_DESCRIPTOR_READ_NOPERMISSION); 751 sendBroadcast(intent); 752 } 753 notifyDescriptorWriteNoPermission()754 private void notifyDescriptorWriteNoPermission() { 755 showMessage("Descriptor write: NoPermission"); 756 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_NOPERMISSION); 757 sendBroadcast(intent); 758 } 759 notifyDescriptorReadNeedEncrypted(String value)760 private void notifyDescriptorReadNeedEncrypted(String value) { 761 showMessage("Descriptor read with encrypted: " + value); 762 Intent intent = new Intent(BLE_DESCRIPTOR_READ_NEED_ENCRYPTED); 763 sendBroadcast(intent); 764 } 765 notifyDescriptorWriteNeedEncrypted(String value)766 private void notifyDescriptorWriteNeedEncrypted(String value) { 767 showMessage("Descriptor write with encrypted: " + value); 768 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_NEED_ENCRYPTED); 769 sendBroadcast(intent); 770 } 771 notifyReliableWriteCompleted()772 private void notifyReliableWriteCompleted() { 773 showMessage("Reliable write complete"); 774 Intent intent = new Intent(BLE_RELIABLE_WRITE_COMPLETED); 775 sendBroadcast(intent); 776 } 777 notifyReliableWriteBadRespCompleted(String err)778 private void notifyReliableWriteBadRespCompleted(String err) { 779 showMessage("Reliable write(bad response) complete"); 780 Intent intent = new Intent(BLE_RELIABLE_WRITE_BAD_RESP_COMPLETED); 781 if (err != null) { 782 intent.putExtra(EXTRA_ERROR_MESSAGE, err); 783 } 784 sendBroadcast(intent); 785 } 786 notifyReadRemoteRssi(int rssi)787 private void notifyReadRemoteRssi(int rssi) { 788 showMessage("Remote rssi read: " + rssi); 789 Intent intent = new Intent(BLE_READ_REMOTE_RSSI); 790 intent.putExtra(EXTRA_RSSI_VALUE, rssi); 791 sendBroadcast(intent); 792 } 793 getService(UUID serverUid)794 private BluetoothGattService getService(UUID serverUid) { 795 BluetoothGattService service = null; 796 797 if (mBluetoothGatt != null) { 798 service = mBluetoothGatt.getService(serverUid); 799 if (service == null) { 800 showMessage("Service not found"); 801 } 802 } 803 return service; 804 } 805 getService()806 private BluetoothGattService getService() { 807 BluetoothGattService service = null; 808 809 if (mBluetoothGatt != null) { 810 service = mBluetoothGatt.getService(SERVICE_UUID); 811 if (service == null) { 812 showMessage("Service not found"); 813 } 814 } 815 return service; 816 } 817 getCharacteristic(UUID serverUid, UUID characteristicUid)818 private BluetoothGattCharacteristic getCharacteristic(UUID serverUid, UUID characteristicUid) { 819 BluetoothGattCharacteristic characteristic = null; 820 821 BluetoothGattService service = getService(serverUid); 822 if (service != null) { 823 characteristic = service.getCharacteristic(characteristicUid); 824 if (characteristic == null) { 825 showMessage("Characteristic not found"); 826 } 827 } 828 return characteristic; 829 } getCharacteristic(UUID uuid)830 private BluetoothGattCharacteristic getCharacteristic(UUID uuid) { 831 BluetoothGattCharacteristic characteristic = null; 832 833 BluetoothGattService service = getService(); 834 if (service != null) { 835 characteristic = service.getCharacteristic(uuid); 836 if (characteristic == null) { 837 showMessage("Characteristic not found"); 838 } 839 } 840 return characteristic; 841 } 842 getDescriptor(UUID uid)843 private BluetoothGattDescriptor getDescriptor(UUID uid) { 844 BluetoothGattDescriptor descriptor = null; 845 846 BluetoothGattCharacteristic characteristic = getCharacteristic(CHARACTERISTIC_UUID); 847 if (characteristic != null) { 848 descriptor = characteristic.getDescriptor(uid); 849 if (descriptor == null) { 850 showMessage("Descriptor not found"); 851 } 852 } 853 return descriptor; 854 } 855 getDescriptor(UUID cuid, UUID duid)856 private BluetoothGattDescriptor getDescriptor(UUID cuid, UUID duid) { 857 BluetoothGattDescriptor descriptor = null; 858 859 BluetoothGattCharacteristic characteristic = getCharacteristic(cuid); 860 if (characteristic != null) { 861 descriptor = characteristic.getDescriptor(duid); 862 if (descriptor == null) { 863 showMessage("Descriptor not found"); 864 } 865 } 866 return descriptor; 867 } 868 showMessage(final String msg)869 private void showMessage(final String msg) { 870 mHandler.post(new Runnable() { 871 public void run() { 872 Toast.makeText(BleClientService.this, msg, Toast.LENGTH_SHORT).show(); 873 } 874 }); 875 } 876 sleep(int millis)877 private void sleep(int millis) { 878 try { 879 Thread.sleep(millis); 880 } catch (InterruptedException e) { 881 Log.e(TAG, "Error in thread sleep", e); 882 } 883 } 884 reliableWrite()885 private void reliableWrite() { 886 // aborting test 887 mBluetoothGatt.beginReliableWrite(); 888 sleep(1000); 889 mBluetoothGatt.abortReliableWrite(); 890 891 // writing test 892 sleep(2000); 893 mBluetoothGatt.beginReliableWrite(); 894 sleep(1000); 895 896 if (BLE_CLIENT_ACTION_RELIABLE_WRITE.equals(mCurrentAction)) { 897 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_WRITE_1ST_DATA; 898 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE); 899 } else { 900 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_BAD_RESP; 901 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_BAD_RESP); 902 } 903 } 904 905 private int mBleState = BluetoothProfile.STATE_DISCONNECTED; 906 private final BluetoothGattCallback mGattCallbacks = new BluetoothGattCallback() { 907 @Override 908 public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { 909 if (DEBUG) Log.d(TAG, "onConnectionStateChange: status= " + status + ", newState= " + newState); 910 if (status == BluetoothGatt.GATT_SUCCESS) { 911 if (newState == BluetoothProfile.STATE_CONNECTED) { 912 mBleState = newState; 913 int bond = gatt.getDevice().getBondState(); 914 boolean bonded = false; 915 BluetoothDevice target = gatt.getDevice(); 916 Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices(); 917 if (pairedDevices.size() > 0) { 918 for (BluetoothDevice device : pairedDevices) { 919 if (device.getAddress().equals(target.getAddress())) { 920 bonded = true; 921 break; 922 } 923 } 924 } 925 if (mSecure && ((bond == BluetoothDevice.BOND_NONE) || !bonded)) { 926 // not pairing and execute Secure Test 927 mBluetoothGatt.disconnect(); 928 notifyMismatchSecure(); 929 } else if (!mSecure && ((bond != BluetoothDevice.BOND_NONE) || bonded)) { 930 // already pairing nad execute Insecure Test 931 mBluetoothGatt.disconnect(); 932 notifyMismatchInsecure(); 933 } else { 934 notifyConnected(); 935 } 936 } else if (status == BluetoothProfile.STATE_DISCONNECTED) { 937 mBleState = newState; 938 mSecure = false; 939 mBluetoothGatt.close(); 940 notifyDisconnected(); 941 } 942 } else { 943 showMessage("Failed to connect: " + status + " , newState = " + newState); 944 mBluetoothGatt.close(); 945 mBluetoothGatt = null; 946 } 947 } 948 949 @Override 950 public void onServicesDiscovered(BluetoothGatt gatt, int status) { 951 if (DEBUG){ 952 Log.d(TAG, "onServiceDiscovered"); 953 } 954 if ((status == BluetoothGatt.GATT_SUCCESS) && (mBluetoothGatt.getService(SERVICE_UUID) != null)) { 955 notifyServicesDiscovered(); 956 } 957 } 958 959 @Override 960 public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { 961 super.onMtuChanged(gatt, mtu, status); 962 if (DEBUG){ 963 Log.d(TAG, "onMtuChanged"); 964 } 965 if (status == BluetoothGatt.GATT_SUCCESS) { 966 // verify MTU size 967 int requestedMtu; 968 if (BLE_CLIENT_ACTION_REQUEST_MTU_23.equals(mCurrentAction)) { 969 requestedMtu = 23; 970 } else if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction)) { 971 requestedMtu = 512; 972 } else { 973 throw new IllegalStateException("unexpected action: " + mCurrentAction); 974 } 975 if (mtu != requestedMtu) { 976 String msg = String.format(getString(R.string.ble_mtu_mismatch_message), 977 requestedMtu, mtu); 978 showMessage(msg); 979 } 980 981 // test writing characteristic 982 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_512BYTES_FOR_MTU); 983 } else { 984 notifyError("Failed to request mtu: " + status); 985 } 986 } 987 988 @Override 989 public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, final int status) { 990 String value = characteristic.getStringValue(0); 991 final UUID uid = characteristic.getUuid(); 992 if (DEBUG) { 993 Log.d(TAG, "onCharacteristicWrite: characteristic.val=" + value + " status=" + status); 994 } 995 996 if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction) || 997 BLE_CLIENT_ACTION_REQUEST_MTU_23.equals(mCurrentAction)) { 998 if (status == BluetoothGatt.GATT_SUCCESS) { 999 notifyMtuChanged(); 1000 } else { 1001 notifyError("Failed to write characteristic: " + status + " : " + uid); 1002 } 1003 } else { 1004 switch (mExecReliableWrite) { 1005 case RELIABLE_WRITE_NONE: 1006 if (status == BluetoothGatt.GATT_SUCCESS) { 1007 if (characteristic.getUuid().equals(CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID)) { 1008 notifyCharacteristicWriteNeedEncrypted(value); 1009 } else if (!characteristic.getUuid().equals(CHARACTERISTIC_RESULT_UUID)) { 1010 // verify 1011 if (Arrays.equals(BleClientService.WRITE_VALUE.getBytes(), characteristic.getValue())) { 1012 notifyCharacteristicWrite(value); 1013 } else { 1014 notifyError("Written data is not correct"); 1015 } 1016 } 1017 } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) { 1018 if (uid.equals(CHARACTERISTIC_NO_WRITE_UUID)) { 1019 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), BleServerService.WRITE_NO_PERMISSION); 1020 notifyCharacteristicWriteNoPermission(value); 1021 } else { 1022 notifyError("Not Permission Write: " + status + " : " + uid); 1023 } 1024 } else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) { 1025 notifyError("Not Authentication Write: " + status + " : " + uid); 1026 } else { 1027 notifyError("Failed to write characteristic: " + status + " : " + uid); 1028 } 1029 break; 1030 case RELIABLE_WRITE_WRITE_1ST_DATA: 1031 // verify 1032 if (WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE.equals(value)) { 1033 // write next data 1034 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_WRITE_2ND_DATA; 1035 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE); 1036 } else { 1037 notifyError("Failed to write characteristic: " + status + " : " + uid); 1038 } 1039 break; 1040 case RELIABLE_WRITE_WRITE_2ND_DATA: 1041 // verify 1042 if (WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE.equals(value)) { 1043 // execute write 1044 mTaskQueue.addTask(new Runnable() { 1045 @Override 1046 public void run() { 1047 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_EXECUTE; 1048 if (!mBluetoothGatt.executeReliableWrite()) { 1049 notifyError("reliable write failed"); 1050 } 1051 } 1052 }, 1000); 1053 } else { 1054 notifyError("Failed to write characteristic: " + status + " : " + uid); 1055 } 1056 break; 1057 case RELIABLE_WRITE_BAD_RESP: 1058 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 1059 // verify response 1060 // Server sends empty response for this test. 1061 // Response must be empty. 1062 String err = null; 1063 if (!TextUtils.isEmpty(value)) { 1064 err = "response is not empty"; 1065 showMessage(err); 1066 } 1067 // finish reliable write 1068 final String errValue = err; 1069 mTaskQueue.addTask(new Runnable() { 1070 @Override 1071 public void run() { 1072 mBluetoothGatt.abortReliableWrite(); 1073 notifyReliableWriteBadRespCompleted(errValue); 1074 } 1075 }, 1000); 1076 break; 1077 } 1078 } 1079 } 1080 1081 @Override 1082 public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { 1083 UUID uid = characteristic.getUuid(); 1084 if (DEBUG) { 1085 Log.d(TAG, "onCharacteristicRead: status=" + status); 1086 } 1087 if (status == BluetoothGatt.GATT_SUCCESS) { 1088 String value = characteristic.getStringValue(0); 1089 if (characteristic.getUuid().equals(CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID)) { 1090 notifyCharacteristicReadNeedEncrypted(value); 1091 } else { 1092 // verify 1093 if (BleServerService.WRITE_VALUE.equals(value)) { 1094 notifyCharacteristicRead(value); 1095 } else { 1096 notifyError("Read data is not correct"); 1097 } 1098 } 1099 } else if (status == BluetoothGatt.GATT_READ_NOT_PERMITTED) { 1100 if (uid.equals(CHARACTERISTIC_NO_READ_UUID)) { 1101 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), BleServerService.READ_NO_PERMISSION); 1102 notifyCharacteristicReadNoPermission(); 1103 } else { 1104 notifyError("Not Permission Read: " + status + " : " + uid); 1105 } 1106 } else if(status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) { 1107 notifyError("Not Authentication Read: " + status + " : " + uid); 1108 } else { 1109 notifyError("Failed to read characteristic: " + status + " : " + uid); 1110 } 1111 } 1112 1113 @Override 1114 public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { 1115 if (DEBUG) { 1116 Log.d(TAG, "onDescriptorWrite"); 1117 } 1118 UUID uid = descriptor.getUuid(); 1119 if ((status == BluetoothGatt.GATT_SUCCESS)) { 1120 if (uid.equals(UPDATE_DESCRIPTOR_UUID)) { 1121 Log.d(TAG, "write in update descriptor."); 1122 if (descriptor.getValue() == BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE) { 1123 notifyDisableNotificationCompletion(); 1124 } 1125 } else if (uid.equals(DESCRIPTOR_UUID)) { 1126 // verify 1127 if (Arrays.equals(WRITE_VALUE.getBytes(), descriptor.getValue())) { 1128 notifyDescriptorWrite(new String(descriptor.getValue())); 1129 } else { 1130 notifyError("Written data is not correct"); 1131 } 1132 } else if (uid.equals(DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID)) { 1133 notifyDescriptorWriteNeedEncrypted(new String(descriptor.getValue())); 1134 } 1135 } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) { 1136 if (uid.equals(DESCRIPTOR_NO_WRITE_UUID)) { 1137 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), BleServerService.DESCRIPTOR_WRITE_NO_PERMISSION); 1138 notifyDescriptorWriteNoPermission(); 1139 } else { 1140 notifyError("Not Permission Write: " + status + " : " + descriptor.getUuid()); 1141 } 1142 } else { 1143 notifyError("Failed to write descriptor"); 1144 } 1145 } 1146 1147 @Override 1148 public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { 1149 if (DEBUG) { 1150 Log.d(TAG, "onDescriptorRead"); 1151 } 1152 1153 UUID uid = descriptor.getUuid(); 1154 if ((status == BluetoothGatt.GATT_SUCCESS)) { 1155 if ((uid != null) && (uid.equals(DESCRIPTOR_UUID))) { 1156 // verify 1157 if (Arrays.equals(BleServerService.WRITE_VALUE.getBytes(), descriptor.getValue())) { 1158 notifyDescriptorRead(new String(descriptor.getValue())); 1159 } else { 1160 notifyError("Read data is not correct"); 1161 } 1162 } else if (uid.equals(DESCRIPTOR_NEED_ENCRYPTED_READ_UUID)) { 1163 notifyDescriptorReadNeedEncrypted(new String(descriptor.getValue())); 1164 } 1165 } else if (status == BluetoothGatt.GATT_READ_NOT_PERMITTED) { 1166 if (uid.equals(DESCRIPTOR_NO_READ_UUID)) { 1167 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), BleServerService.DESCRIPTOR_READ_NO_PERMISSION); 1168 notifyDescriptorReadNoPermission(); 1169 } else { 1170 notifyError("Not Permission Read: " + status + " : " + descriptor.getUuid()); 1171 } 1172 } else { 1173 notifyError("Failed to read descriptor: " + status); 1174 } 1175 } 1176 1177 @Override 1178 public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { 1179 UUID uid = characteristic.getUuid(); 1180 if (DEBUG) { 1181 Log.d(TAG, "onCharacteristicChanged: " + uid); 1182 } 1183 if (uid != null) { 1184 if (uid.equals(INDICATE_CHARACTERISTIC_UUID)) { 1185 setNotification(characteristic, false); 1186 notifyCharacteristicIndicated(); 1187 } else { 1188 mNotifyCount--; 1189 setNotification(characteristic, false); 1190 if (mNotifyCount == 0) { 1191 notifyCharacteristicChanged(); 1192 } 1193 } 1194 } 1195 } 1196 1197 @Override 1198 public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { 1199 if (DEBUG) { 1200 Log.d(TAG, "onReliableWriteComplete: " + status); 1201 } 1202 1203 if (mExecReliableWrite != ReliableWriteState.RELIABLE_WRITE_NONE) { 1204 if (status == BluetoothGatt.GATT_SUCCESS) { 1205 notifyReliableWriteCompleted(); 1206 } else { 1207 notifyError("Failed to complete reliable write: " + status); 1208 } 1209 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 1210 } 1211 } 1212 1213 @Override 1214 public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { 1215 if (DEBUG) { 1216 Log.d(TAG, "onReadRemoteRssi"); 1217 } 1218 if (status == BluetoothGatt.GATT_SUCCESS) { 1219 notifyReadRemoteRssi(rssi); 1220 } else { 1221 notifyError("Failed to read remote rssi"); 1222 } 1223 } 1224 }; 1225 1226 private final ScanCallback mScanCallback = new ScanCallback() { 1227 @Override 1228 public void onScanResult(int callbackType, ScanResult result) { 1229 if (mBluetoothGatt == null) { 1230 // verify the validity of the advertisement packet. 1231 mValidityService = false; 1232 List<ParcelUuid> uuids = result.getScanRecord().getServiceUuids(); 1233 for (ParcelUuid uuid : uuids) { 1234 if (uuid.getUuid().equals(BleServerService.ADV_SERVICE_UUID)) { 1235 mValidityService = true; 1236 break; 1237 } 1238 } 1239 if (mValidityService) { 1240 stopScan(); 1241 1242 BluetoothDevice device = result.getDevice(); 1243 if (mSecure) { 1244 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { 1245 if (!device.createBond()) { 1246 notifyError("Failed to call create bond"); 1247 } 1248 } else { 1249 mBluetoothGatt = connectGatt(result.getDevice(), mContext, false, mSecure, mGattCallbacks); 1250 } 1251 } else { 1252 mBluetoothGatt = connectGatt(result.getDevice(), mContext, false, mSecure, mGattCallbacks); 1253 } 1254 } else { 1255 notifyError("There is no validity to Advertise servie."); 1256 } 1257 } 1258 } 1259 }; 1260 startScan()1261 private void startScan() { 1262 if (DEBUG) Log.d(TAG, "startScan"); 1263 List<ScanFilter> filter = Arrays.asList(new ScanFilter.Builder().setServiceUuid( 1264 new ParcelUuid(BleServerService.ADV_SERVICE_UUID)).build()); 1265 ScanSettings setting = new ScanSettings.Builder() 1266 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 1267 mScanner.startScan(filter, setting, mScanCallback); 1268 } 1269 stopScan()1270 private void stopScan() { 1271 if (DEBUG) Log.d(TAG, "stopScan"); 1272 if (mScanner != null) { 1273 mScanner.stopScan(mScanCallback); 1274 } 1275 } 1276 createTestData(int length)1277 private static String createTestData(int length) { 1278 StringBuilder builder = new StringBuilder(); 1279 builder.append("REQUEST_MTU"); 1280 int len = length - builder.length(); 1281 for (int i = 0; i < len; ++i) { 1282 builder.append(""+(i%10)); 1283 } 1284 return builder.toString(); 1285 } 1286 1287 private final BroadcastReceiver mBondStatusReceiver = new BroadcastReceiver() { 1288 @Override 1289 public void onReceive(Context context, Intent intent) { 1290 if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) { 1291 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 1292 int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE); 1293 switch (state) { 1294 case BluetoothDevice.BOND_BONDED: 1295 if ((mBluetoothGatt == null) && 1296 (device.getType() != BluetoothDevice.DEVICE_TYPE_CLASSIC)) { 1297 if (DEBUG) { 1298 Log.d(TAG, "onReceive:BOND_BONDED: calling connectGatt device=" 1299 + device + ", mSecure=" + mSecure); 1300 } 1301 mBluetoothGatt = connectGatt(device, mContext, false, mSecure, 1302 mGattCallbacks); 1303 } 1304 break; 1305 case BluetoothDevice.BOND_NONE: 1306 notifyError("Failed to create bond."); 1307 break; 1308 case BluetoothDevice.BOND_BONDING: 1309 default: // fall through 1310 // wait for next state 1311 break; 1312 } 1313 } 1314 } 1315 }; 1316 } 1317