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_DISVOCER_SERVICE = 152 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_BLE_DISVOCER_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 private enum ReliableWriteState { 302 RELIABLE_WRITE_NONE, 303 RELIABLE_WRITE_WRITE_1ST_DATA, 304 RELIABLE_WRITE_WRITE_2ND_DATA, 305 RELIABLE_WRITE_EXECUTE, 306 RELIABLE_WRITE_BAD_RESP 307 } 308 309 @Override onCreate()310 public void onCreate() { 311 super.onCreate(); 312 313 registerReceiver(mBondStatusReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED)); 314 315 mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 316 mBluetoothAdapter = mBluetoothManager.getAdapter(); 317 mScanner = mBluetoothAdapter.getBluetoothLeScanner(); 318 mHandler = new Handler(); 319 mContext = this; 320 mNotifyCount = 0; 321 322 mTaskQueue = new TestTaskQueue(getClass().getName() + "_taskHandlerThread"); 323 } 324 325 @Override onStartCommand(final Intent intent, int flags, int startId)326 public int onStartCommand(final Intent intent, int flags, int startId) { 327 if (!mBluetoothAdapter.isEnabled()) { 328 notifyBluetoothDisabled(); 329 } else { 330 mTaskQueue.addTask(new Runnable() { 331 @Override 332 public void run() { 333 onTestFinish(intent.getAction()); 334 } 335 }, 1500); 336 } 337 return START_NOT_STICKY; 338 } 339 onTestFinish(String action)340 private void onTestFinish(String action) { 341 mCurrentAction = action; 342 if (mCurrentAction != null) { 343 switch (mCurrentAction) { 344 case BLE_CLIENT_ACTION_CLIENT_CONNECT_SECURE: 345 mSecure = true; 346 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 347 startScan(); 348 break; 349 case BLE_CLIENT_ACTION_CLIENT_CONNECT: 350 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 351 startScan(); 352 break; 353 case BLE_CLIENT_ACTION_BLE_DISVOCER_SERVICE: 354 if (mBluetoothGatt != null && mBleState == BluetoothProfile.STATE_CONNECTED) { 355 mBluetoothGatt.discoverServices(); 356 } else { 357 showMessage("Bluetooth LE not cnnected."); 358 } 359 break; 360 case BLE_CLIENT_ACTION_REQUEST_MTU_23: 361 case BLE_CLIENT_ACTION_REQUEST_MTU_512: // fall through 362 requestMtu(); 363 break; 364 case BLE_CLIENT_ACTION_READ_CHARACTERISTIC: 365 readCharacteristic(CHARACTERISTIC_UUID); 366 break; 367 case BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC: 368 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE); 369 break; 370 case BLE_CLIENT_ACTION_RELIABLE_WRITE: 371 case BLE_CLIENT_ACTION_RELIABLE_WRITE_BAD_RESP: // fall through 372 mTaskQueue.addTask(new Runnable() { 373 @Override 374 public void run() { 375 reliableWrite(); 376 } 377 }); 378 break; 379 case BLE_CLIENT_ACTION_INDICATE_CHARACTERISTIC: 380 setNotification(INDICATE_CHARACTERISTIC_UUID, true); 381 break; 382 case BLE_CLIENT_ACTION_NOTIFY_CHARACTERISTIC: 383 // Registered the notify to characteristics in the service 384 mTaskQueue.addTask(new Runnable() { 385 @Override 386 public void run() { 387 mNotifyCount = 16; 388 setNotification(UPDATE_CHARACTERISTIC_UUID, true); 389 sleep(1000); 390 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_1, true); 391 sleep(1000); 392 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_2, true); 393 sleep(1000); 394 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_3, true); 395 sleep(1000); 396 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_4, true); 397 sleep(1000); 398 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_5, true); 399 sleep(1000); 400 setNotification(UPDATE_CHARACTERISTIC_UUID_6, true); 401 sleep(1000); 402 setNotification(UPDATE_CHARACTERISTIC_UUID_7, true); 403 sleep(1000); 404 setNotification(UPDATE_CHARACTERISTIC_UUID_8, true); 405 sleep(1000); 406 setNotification(UPDATE_CHARACTERISTIC_UUID_9, true); 407 sleep(1000); 408 setNotification(UPDATE_CHARACTERISTIC_UUID_10, true); 409 sleep(1000); 410 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_11, true); 411 sleep(1000); 412 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_12, true); 413 sleep(1000); 414 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_13, true); 415 sleep(1000); 416 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_14, true); 417 sleep(1000); 418 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_15, true); 419 sleep(1000); 420 } 421 }); 422 break; 423 case BLE_CLIENT_ACTION_READ_DESCRIPTOR: 424 readDescriptor(DESCRIPTOR_UUID); 425 break; 426 case BLE_CLIENT_ACTION_WRITE_DESCRIPTOR: 427 writeDescriptor(DESCRIPTOR_UUID, WRITE_VALUE); 428 break; 429 case BLE_CLIENT_ACTION_READ_RSSI: 430 if (mBluetoothGatt != null) { 431 mBluetoothGatt.readRemoteRssi(); 432 } 433 break; 434 case BLE_CLIENT_ACTION_CLIENT_DISCONNECT: 435 if (mBluetoothGatt != null) { 436 mBluetoothGatt.disconnect(); 437 } 438 break; 439 case BLE_CLIENT_ACTION_READ_CHARACTERISTIC_NO_PERMISSION: 440 readCharacteristic(CHARACTERISTIC_NO_READ_UUID); 441 break; 442 case BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC_NO_PERMISSION: 443 writeCharacteristic(CHARACTERISTIC_NO_WRITE_UUID, WRITE_VALUE); 444 break; 445 case BLE_CLIENT_ACTION_READ_DESCRIPTOR_NO_PERMISSION: 446 readDescriptor(DESCRIPTOR_NO_READ_UUID); 447 break; 448 case BLE_CLIENT_ACTION_WRITE_DESCRIPTOR_NO_PERMISSION: 449 writeDescriptor(DESCRIPTOR_NO_WRITE_UUID, WRITE_VALUE); 450 break; 451 case BLE_CLIENT_ACTION_READ_AUTHENTICATED_CHARACTERISTIC: 452 readCharacteristic(CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID); 453 break; 454 case BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_CHARACTERISTIC: 455 writeCharacteristic(CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID, WRITE_VALUE); 456 break; 457 case BLE_CLIENT_ACTION_READ_AUTHENTICATED_DESCRIPTOR: 458 readDescriptor(CHARACTERISTIC_RESULT_UUID, DESCRIPTOR_NEED_ENCRYPTED_READ_UUID); 459 break; 460 case BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_DESCRIPTOR: 461 writeDescriptor(CHARACTERISTIC_RESULT_UUID, DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID, WRITE_VALUE); 462 break; 463 } 464 } 465 } 466 467 @Override onBind(Intent intent)468 public IBinder onBind(Intent intent) { 469 return null; 470 } 471 472 @Override onDestroy()473 public void onDestroy() { 474 super.onDestroy(); 475 if (mBluetoothGatt != null) { 476 mBluetoothGatt.disconnect(); 477 mBluetoothGatt.close(); 478 mBluetoothGatt = null; 479 } 480 stopScan(); 481 unregisterReceiver(mBondStatusReceiver); 482 483 mTaskQueue.quit(); 484 } 485 connectGatt(BluetoothDevice device, Context context, boolean autoConnect, boolean isSecure, BluetoothGattCallback callback)486 public static BluetoothGatt connectGatt(BluetoothDevice device, Context context, boolean autoConnect, boolean isSecure, BluetoothGattCallback callback) { 487 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 488 if (isSecure) { 489 if (TRANSPORT_MODE_FOR_SECURE_CONNECTION == BluetoothDevice.TRANSPORT_AUTO) { 490 Toast.makeText(context, "connectGatt(transport=AUTO)", Toast.LENGTH_SHORT).show(); 491 } else { 492 Toast.makeText(context, "connectGatt(transport=LE)", Toast.LENGTH_SHORT).show(); 493 } 494 return device.connectGatt(context, autoConnect, callback, TRANSPORT_MODE_FOR_SECURE_CONNECTION); 495 } else { 496 Toast.makeText(context, "connectGatt(transport=LE)", Toast.LENGTH_SHORT).show(); 497 return device.connectGatt(context, autoConnect, callback, BluetoothDevice.TRANSPORT_LE); 498 } 499 } else { 500 Toast.makeText(context, "connectGatt", Toast.LENGTH_SHORT).show(); 501 return device.connectGatt(context, autoConnect, callback); 502 } 503 } 504 requestMtu()505 private void requestMtu() { 506 if (mBluetoothGatt != null) { 507 // MTU request test does not work on Android 6.0 in secure mode. 508 // (BluetoothDevice#createBond() does not work on Android 6.0. 509 // So devices can't establish Bluetooth LE pairing.) 510 boolean mtuTestExecutable = true; 511 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) { 512 mtuTestExecutable = !mSecure; 513 } 514 515 if (mtuTestExecutable) { 516 int mtu = 0; 517 if (BLE_CLIENT_ACTION_REQUEST_MTU_23.equals(mCurrentAction)) { 518 mtu = 23; 519 } else if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction)) { 520 mtu = 512; 521 } else { 522 throw new IllegalStateException("unexpected action: " + mCurrentAction); 523 } 524 mBluetoothGatt.requestMtu(mtu); 525 } else { 526 showMessage("Skip MTU test."); 527 notifyMtuChanged(); 528 } 529 } 530 } 531 writeCharacteristic(BluetoothGattCharacteristic characteristic, String writeValue)532 private void writeCharacteristic(BluetoothGattCharacteristic characteristic, String writeValue) { 533 if (characteristic != null) { 534 characteristic.setValue(writeValue); 535 mBluetoothGatt.writeCharacteristic(characteristic); 536 } 537 } 538 writeCharacteristic(UUID uid, String writeValue)539 private void writeCharacteristic(UUID uid, String writeValue) { 540 BluetoothGattCharacteristic characteristic = getCharacteristic(uid); 541 if (characteristic != null){ 542 writeCharacteristic(characteristic, writeValue); 543 } 544 } 545 readCharacteristic(UUID uuid)546 private void readCharacteristic(UUID uuid) { 547 BluetoothGattCharacteristic characteristic = getCharacteristic(uuid); 548 if (characteristic != null) { 549 mBluetoothGatt.readCharacteristic(characteristic); 550 } 551 } 552 writeDescriptor(UUID uid, String writeValue)553 private void writeDescriptor(UUID uid, String writeValue) { 554 BluetoothGattDescriptor descriptor = getDescriptor(uid); 555 if (descriptor != null) { 556 descriptor.setValue(writeValue.getBytes()); 557 mBluetoothGatt.writeDescriptor(descriptor); 558 } 559 } 560 readDescriptor(UUID uuid)561 private void readDescriptor(UUID uuid) { 562 BluetoothGattDescriptor descriptor = getDescriptor(uuid); 563 if (descriptor != null) { 564 mBluetoothGatt.readDescriptor(descriptor); 565 } 566 } 567 writeDescriptor(UUID cuid, UUID duid, String writeValue)568 private void writeDescriptor(UUID cuid, UUID duid, String writeValue) { 569 BluetoothGattDescriptor descriptor = getDescriptor(cuid, duid); 570 if (descriptor != null) { 571 descriptor.setValue(writeValue.getBytes()); 572 mBluetoothGatt.writeDescriptor(descriptor); 573 } 574 } 575 readDescriptor(UUID cuid, UUID duid)576 private void readDescriptor(UUID cuid, UUID duid) { 577 BluetoothGattDescriptor descriptor = getDescriptor(cuid, duid); 578 if (descriptor != null) { 579 mBluetoothGatt.readDescriptor(descriptor); 580 } 581 } 582 setNotification(BluetoothGattCharacteristic characteristic, boolean enable)583 private void setNotification(BluetoothGattCharacteristic characteristic, boolean enable) { 584 if (characteristic != null) { 585 mBluetoothGatt.setCharacteristicNotification(characteristic, enable); 586 BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UPDATE_DESCRIPTOR_UUID); 587 if (enable) { 588 if (characteristic.getUuid().equals(INDICATE_CHARACTERISTIC_UUID)) { 589 descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE); 590 } else { 591 descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); 592 } 593 } else { 594 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 595 } 596 mBluetoothGatt.writeDescriptor(descriptor); 597 } 598 } 599 setNotification(boolean enable)600 private void setNotification(boolean enable) { 601 BluetoothGattCharacteristic characteristic = getCharacteristic(UPDATE_CHARACTERISTIC_UUID); 602 if (characteristic != null) { 603 setNotification(characteristic, enable); 604 } 605 } 606 setNotification(UUID serviceUid, UUID characteristicUid, boolean enable)607 private void setNotification(UUID serviceUid, UUID characteristicUid, boolean enable) { 608 BluetoothGattCharacteristic characteristic = getCharacteristic(serviceUid, characteristicUid); 609 if (characteristic != null) { 610 setNotification(characteristic, enable); 611 } 612 } 613 setNotification(UUID uid, boolean enable)614 private void setNotification(UUID uid, boolean enable) { 615 BluetoothGattCharacteristic characteristic = getCharacteristic(uid); 616 if (characteristic != null) { 617 setNotification(characteristic, enable); 618 } 619 } 620 notifyError(String message)621 private void notifyError(String message) { 622 showMessage(message); 623 Log.i(TAG, message); 624 625 Intent intent = new Intent(BLE_CLIENT_ERROR); 626 sendBroadcast(intent); 627 } 628 notifyMismatchSecure()629 private void notifyMismatchSecure() { 630 Intent intent = new Intent(BLE_BLUETOOTH_MISMATCH_SECURE); 631 sendBroadcast(intent); 632 } 633 notifyMismatchInsecure()634 private void notifyMismatchInsecure() { 635 Intent intent = new Intent(BLE_BLUETOOTH_MISMATCH_INSECURE); 636 sendBroadcast(intent); 637 } 638 notifyBluetoothDisabled()639 private void notifyBluetoothDisabled() { 640 Intent intent = new Intent(BLE_BLUETOOTH_DISABLED); 641 sendBroadcast(intent); 642 } 643 notifyConnected()644 private void notifyConnected() { 645 showMessage("Bluetooth LE connected"); 646 Intent intent = new Intent(BLE_BLUETOOTH_CONNECTED); 647 sendBroadcast(intent); 648 } 649 notifyDisconnected()650 private void notifyDisconnected() { 651 showMessage("Bluetooth LE disconnected"); 652 Intent intent = new Intent(BLE_BLUETOOTH_DISCONNECTED); 653 sendBroadcast(intent); 654 } 655 notifyServicesDiscovered()656 private void notifyServicesDiscovered() { 657 showMessage("Service discovered"); 658 Intent intent = new Intent(BLE_SERVICES_DISCOVERED); 659 sendBroadcast(intent); 660 } 661 notifyMtuChanged()662 private void notifyMtuChanged() { 663 Intent intent; 664 if (BLE_CLIENT_ACTION_REQUEST_MTU_23.equals(mCurrentAction)) { 665 intent = new Intent(BLE_MTU_CHANGED_23BYTES); 666 } else if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction)) { 667 intent = new Intent(BLE_MTU_CHANGED_512BYTES); 668 } else { 669 throw new IllegalStateException("unexpected action: " + mCurrentAction); 670 } 671 sendBroadcast(intent); 672 } 673 notifyCharacteristicRead(String value)674 private void notifyCharacteristicRead(String value) { 675 showMessage("Characteristic read: " + value); 676 Intent intent = new Intent(BLE_CHARACTERISTIC_READ); 677 intent.putExtra(EXTRA_CHARACTERISTIC_VALUE, value); 678 sendBroadcast(intent); 679 } 680 notifyCharacteristicWrite(String value)681 private void notifyCharacteristicWrite(String value) { 682 showMessage("Characteristic write: " + value); 683 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE); 684 sendBroadcast(intent); 685 } 686 notifyCharacteristicReadNoPermission()687 private void notifyCharacteristicReadNoPermission() { 688 showMessage("Characteristic not read: No Permission"); 689 Intent intent = new Intent(BLE_CHARACTERISTIC_READ_NOPERMISSION); 690 sendBroadcast(intent); 691 } 692 notifyCharacteristicWriteNoPermission(String value)693 private void notifyCharacteristicWriteNoPermission(String value) { 694 showMessage("Characteristic write: No Permission"); 695 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_NOPERMISSION); 696 sendBroadcast(intent); 697 } 698 notifyCharacteristicReadNeedEncrypted(String value)699 private void notifyCharacteristicReadNeedEncrypted(String value) { 700 showMessage("Characteristic read with encrypted: " + value); 701 Intent intent = new Intent(BLE_CHARACTERISTIC_READ_NEED_ENCRYPTED); 702 sendBroadcast(intent); 703 } 704 notifyCharacteristicWriteNeedEncrypted(String value)705 private void notifyCharacteristicWriteNeedEncrypted(String value) { 706 showMessage("Characteristic write with encrypted: " + value); 707 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_NEED_ENCRYPTED); 708 sendBroadcast(intent); 709 } 710 notifyCharacteristicChanged()711 private void notifyCharacteristicChanged() { 712 showMessage("Characteristic changed"); 713 Intent intent = new Intent(BLE_CHARACTERISTIC_CHANGED); 714 sendBroadcast(intent); 715 } 716 notifyCharacteristicIndicated()717 private void notifyCharacteristicIndicated() { 718 showMessage("Characteristic Indicated"); 719 Intent intent = new Intent(BLE_CHARACTERISTIC_INDICATED); 720 sendBroadcast(intent); 721 } 722 notifyDescriptorRead(String value)723 private void notifyDescriptorRead(String value) { 724 showMessage("Descriptor read: " + value); 725 Intent intent = new Intent(BLE_DESCRIPTOR_READ); 726 intent.putExtra(EXTRA_DESCRIPTOR_VALUE, value); 727 sendBroadcast(intent); 728 } 729 notifyDescriptorWrite(String value)730 private void notifyDescriptorWrite(String value) { 731 showMessage("Descriptor write: " + value); 732 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE); 733 sendBroadcast(intent); 734 } 735 notifyDescriptorReadNoPermission()736 private void notifyDescriptorReadNoPermission() { 737 showMessage("Descriptor read: No Permission"); 738 Intent intent = new Intent(BLE_DESCRIPTOR_READ_NOPERMISSION); 739 sendBroadcast(intent); 740 } 741 notifyDescriptorWriteNoPermission()742 private void notifyDescriptorWriteNoPermission() { 743 showMessage("Descriptor write: NoPermission"); 744 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_NOPERMISSION); 745 sendBroadcast(intent); 746 } 747 notifyDescriptorReadNeedEncrypted(String value)748 private void notifyDescriptorReadNeedEncrypted(String value) { 749 showMessage("Descriptor read with encrypted: " + value); 750 Intent intent = new Intent(BLE_DESCRIPTOR_READ_NEED_ENCRYPTED); 751 sendBroadcast(intent); 752 } 753 notifyDescriptorWriteNeedEncrypted(String value)754 private void notifyDescriptorWriteNeedEncrypted(String value) { 755 showMessage("Descriptor write with encrypted: " + value); 756 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_NEED_ENCRYPTED); 757 sendBroadcast(intent); 758 } 759 notifyReliableWriteCompleted()760 private void notifyReliableWriteCompleted() { 761 showMessage("Reliable write compelte"); 762 Intent intent = new Intent(BLE_RELIABLE_WRITE_COMPLETED); 763 sendBroadcast(intent); 764 } 765 notifyReliableWriteBadRespCompleted(String err)766 private void notifyReliableWriteBadRespCompleted(String err) { 767 showMessage("Reliable write(bad response) compelte"); 768 Intent intent = new Intent(BLE_RELIABLE_WRITE_BAD_RESP_COMPLETED); 769 if (err != null) { 770 intent.putExtra(EXTRA_ERROR_MESSAGE, err); 771 } 772 sendBroadcast(intent); 773 } 774 notifyReadRemoteRssi(int rssi)775 private void notifyReadRemoteRssi(int rssi) { 776 showMessage("Remote rssi read: " + rssi); 777 Intent intent = new Intent(BLE_READ_REMOTE_RSSI); 778 intent.putExtra(EXTRA_RSSI_VALUE, rssi); 779 sendBroadcast(intent); 780 } 781 getService(UUID serverUid)782 private BluetoothGattService getService(UUID serverUid) { 783 BluetoothGattService service = null; 784 785 if (mBluetoothGatt != null) { 786 service = mBluetoothGatt.getService(serverUid); 787 if (service == null) { 788 showMessage("Service not found"); 789 } 790 } 791 return service; 792 } 793 getService()794 private BluetoothGattService getService() { 795 BluetoothGattService service = null; 796 797 if (mBluetoothGatt != null) { 798 service = mBluetoothGatt.getService(SERVICE_UUID); 799 if (service == null) { 800 showMessage("Service not found"); 801 } 802 } 803 return service; 804 } 805 getCharacteristic(UUID serverUid, UUID characteristicUid)806 private BluetoothGattCharacteristic getCharacteristic(UUID serverUid, UUID characteristicUid) { 807 BluetoothGattCharacteristic characteristic = null; 808 809 BluetoothGattService service = getService(serverUid); 810 if (service != null) { 811 characteristic = service.getCharacteristic(characteristicUid); 812 if (characteristic == null) { 813 showMessage("Characteristic not found"); 814 } 815 } 816 return characteristic; 817 } getCharacteristic(UUID uuid)818 private BluetoothGattCharacteristic getCharacteristic(UUID uuid) { 819 BluetoothGattCharacteristic characteristic = null; 820 821 BluetoothGattService service = getService(); 822 if (service != null) { 823 characteristic = service.getCharacteristic(uuid); 824 if (characteristic == null) { 825 showMessage("Characteristic not found"); 826 } 827 } 828 return characteristic; 829 } 830 getDescriptor(UUID uid)831 private BluetoothGattDescriptor getDescriptor(UUID uid) { 832 BluetoothGattDescriptor descriptor = null; 833 834 BluetoothGattCharacteristic characteristic = getCharacteristic(CHARACTERISTIC_UUID); 835 if (characteristic != null) { 836 descriptor = characteristic.getDescriptor(uid); 837 if (descriptor == null) { 838 showMessage("Descriptor not found"); 839 } 840 } 841 return descriptor; 842 } 843 getDescriptor(UUID cuid, UUID duid)844 private BluetoothGattDescriptor getDescriptor(UUID cuid, UUID duid) { 845 BluetoothGattDescriptor descriptor = null; 846 847 BluetoothGattCharacteristic characteristic = getCharacteristic(cuid); 848 if (characteristic != null) { 849 descriptor = characteristic.getDescriptor(duid); 850 if (descriptor == null) { 851 showMessage("Descriptor not found"); 852 } 853 } 854 return descriptor; 855 } 856 showMessage(final String msg)857 private void showMessage(final String msg) { 858 mHandler.post(new Runnable() { 859 public void run() { 860 Toast.makeText(BleClientService.this, msg, Toast.LENGTH_SHORT).show(); 861 } 862 }); 863 } 864 sleep(int millis)865 private void sleep(int millis) { 866 try { 867 Thread.sleep(millis); 868 } catch (InterruptedException e) { 869 Log.e(TAG, "Error in thread sleep", e); 870 } 871 } 872 reliableWrite()873 private void reliableWrite() { 874 // aborting test 875 mBluetoothGatt.beginReliableWrite(); 876 sleep(1000); 877 mBluetoothGatt.abortReliableWrite(); 878 879 // writing test 880 sleep(2000); 881 mBluetoothGatt.beginReliableWrite(); 882 sleep(1000); 883 884 if (BLE_CLIENT_ACTION_RELIABLE_WRITE.equals(mCurrentAction)) { 885 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_WRITE_1ST_DATA; 886 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE); 887 } else { 888 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_BAD_RESP; 889 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_BAD_RESP); 890 } 891 } 892 893 private int mBleState = BluetoothProfile.STATE_DISCONNECTED; 894 private final BluetoothGattCallback mGattCallbacks = new BluetoothGattCallback() { 895 @Override 896 public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { 897 if (DEBUG) Log.d(TAG, "onConnectionStateChange: status= " + status + ", newState= " + newState); 898 if (status == BluetoothGatt.GATT_SUCCESS) { 899 if (newState == BluetoothProfile.STATE_CONNECTED) { 900 mBleState = newState; 901 int bond = gatt.getDevice().getBondState(); 902 boolean bonded = false; 903 BluetoothDevice target = gatt.getDevice(); 904 Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices(); 905 if (pairedDevices.size() > 0) { 906 for (BluetoothDevice device : pairedDevices) { 907 if (device.getAddress().equals(target.getAddress())) { 908 bonded = true; 909 break; 910 } 911 } 912 } 913 if (mSecure && ((bond == BluetoothDevice.BOND_NONE) || !bonded)) { 914 // not pairing and execute Secure Test 915 mBluetoothGatt.disconnect(); 916 notifyMismatchSecure(); 917 } else if (!mSecure && ((bond != BluetoothDevice.BOND_NONE) || bonded)) { 918 // already pairing nad execute Insecure Test 919 mBluetoothGatt.disconnect(); 920 notifyMismatchInsecure(); 921 } else { 922 notifyConnected(); 923 } 924 } else if (status == BluetoothProfile.STATE_DISCONNECTED) { 925 mBleState = newState; 926 mSecure = false; 927 mBluetoothGatt.close(); 928 notifyDisconnected(); 929 } 930 } else { 931 showMessage("Failed to connect: " + status + " , newState = " + newState); 932 mBluetoothGatt.close(); 933 mBluetoothGatt = null; 934 } 935 } 936 937 @Override 938 public void onServicesDiscovered(BluetoothGatt gatt, int status) { 939 if (DEBUG){ 940 Log.d(TAG, "onServiceDiscovered"); 941 } 942 if ((status == BluetoothGatt.GATT_SUCCESS) && (mBluetoothGatt.getService(SERVICE_UUID) != null)) { 943 notifyServicesDiscovered(); 944 } 945 } 946 947 @Override 948 public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { 949 super.onMtuChanged(gatt, mtu, status); 950 if (DEBUG){ 951 Log.d(TAG, "onMtuChanged"); 952 } 953 if (status == BluetoothGatt.GATT_SUCCESS) { 954 // verify MTU size 955 int requestedMtu; 956 if (BLE_CLIENT_ACTION_REQUEST_MTU_23.equals(mCurrentAction)) { 957 requestedMtu = 23; 958 } else if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction)) { 959 requestedMtu = 512; 960 } else { 961 throw new IllegalStateException("unexpected action: " + mCurrentAction); 962 } 963 if (mtu != requestedMtu) { 964 String msg = String.format(getString(R.string.ble_mtu_mismatch_message), 965 requestedMtu, mtu); 966 showMessage(msg); 967 } 968 969 // test writing characteristic 970 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_512BYTES_FOR_MTU); 971 } else { 972 notifyError("Failed to request mtu: " + status); 973 } 974 } 975 976 @Override 977 public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, final int status) { 978 String value = characteristic.getStringValue(0); 979 final UUID uid = characteristic.getUuid(); 980 if (DEBUG) { 981 Log.d(TAG, "onCharacteristicWrite: characteristic.val=" + value + " status=" + status); 982 } 983 984 if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction) || 985 BLE_CLIENT_ACTION_REQUEST_MTU_23.equals(mCurrentAction)) { 986 if (status == BluetoothGatt.GATT_SUCCESS) { 987 notifyMtuChanged(); 988 } else { 989 notifyError("Failed to write characteristic: " + status + " : " + uid); 990 } 991 } else { 992 switch (mExecReliableWrite) { 993 case RELIABLE_WRITE_NONE: 994 if (status == BluetoothGatt.GATT_SUCCESS) { 995 if (characteristic.getUuid().equals(CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID)) { 996 notifyCharacteristicWriteNeedEncrypted(value); 997 } else if (!characteristic.getUuid().equals(CHARACTERISTIC_RESULT_UUID)) { 998 // verify 999 if (Arrays.equals(BleClientService.WRITE_VALUE.getBytes(), characteristic.getValue())) { 1000 notifyCharacteristicWrite(value); 1001 } else { 1002 notifyError("Written data is not correct"); 1003 } 1004 } 1005 } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) { 1006 if (uid.equals(CHARACTERISTIC_NO_WRITE_UUID)) { 1007 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), BleServerService.WRITE_NO_PERMISSION); 1008 notifyCharacteristicWriteNoPermission(value); 1009 } else { 1010 notifyError("Not Permission Write: " + status + " : " + uid); 1011 } 1012 } else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) { 1013 notifyError("Not Authentication Write: " + status + " : " + uid); 1014 } else { 1015 notifyError("Failed to write characteristic: " + status + " : " + uid); 1016 } 1017 break; 1018 case RELIABLE_WRITE_WRITE_1ST_DATA: 1019 // verify 1020 if (WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE.equals(value)) { 1021 // write next data 1022 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_WRITE_2ND_DATA; 1023 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE); 1024 } else { 1025 notifyError("Failed to write characteristic: " + status + " : " + uid); 1026 } 1027 break; 1028 case RELIABLE_WRITE_WRITE_2ND_DATA: 1029 // verify 1030 if (WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE.equals(value)) { 1031 // execute write 1032 mTaskQueue.addTask(new Runnable() { 1033 @Override 1034 public void run() { 1035 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_EXECUTE; 1036 if (!mBluetoothGatt.executeReliableWrite()) { 1037 notifyError("reliable write failed"); 1038 } 1039 } 1040 }, 1000); 1041 } else { 1042 notifyError("Failed to write characteristic: " + status + " : " + uid); 1043 } 1044 break; 1045 case RELIABLE_WRITE_BAD_RESP: 1046 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 1047 // verify response 1048 // Server sends empty response for this test. 1049 // Response must be empty. 1050 String err = null; 1051 if (!TextUtils.isEmpty(value)) { 1052 err = "response is not empty"; 1053 showMessage(err); 1054 } 1055 // finish reliable write 1056 final String errValue = err; 1057 mTaskQueue.addTask(new Runnable() { 1058 @Override 1059 public void run() { 1060 mBluetoothGatt.abortReliableWrite(); 1061 notifyReliableWriteBadRespCompleted(errValue); 1062 } 1063 }, 1000); 1064 break; 1065 } 1066 } 1067 } 1068 1069 @Override 1070 public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { 1071 UUID uid = characteristic.getUuid(); 1072 if (DEBUG) { 1073 Log.d(TAG, "onCharacteristicRead: status=" + status); 1074 } 1075 if (status == BluetoothGatt.GATT_SUCCESS) { 1076 String value = characteristic.getStringValue(0); 1077 if (characteristic.getUuid().equals(CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID)) { 1078 notifyCharacteristicReadNeedEncrypted(value); 1079 } else { 1080 // verify 1081 if (BleServerService.WRITE_VALUE.equals(value)) { 1082 notifyCharacteristicRead(value); 1083 } else { 1084 notifyError("Read data is not correct"); 1085 } 1086 } 1087 } else if (status == BluetoothGatt.GATT_READ_NOT_PERMITTED) { 1088 if (uid.equals(CHARACTERISTIC_NO_READ_UUID)) { 1089 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), BleServerService.READ_NO_PERMISSION); 1090 notifyCharacteristicReadNoPermission(); 1091 } else { 1092 notifyError("Not Permission Read: " + status + " : " + uid); 1093 } 1094 } else if(status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) { 1095 notifyError("Not Authentication Read: " + status + " : " + uid); 1096 } else { 1097 notifyError("Failed to read characteristic: " + status + " : " + uid); 1098 } 1099 } 1100 1101 @Override 1102 public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { 1103 if (DEBUG) { 1104 Log.d(TAG, "onDescriptorWrite"); 1105 } 1106 UUID uid = descriptor.getUuid(); 1107 if ((status == BluetoothGatt.GATT_SUCCESS)) { 1108 if (uid.equals(UPDATE_DESCRIPTOR_UUID)) { 1109 Log.d(TAG, "write in update descriptor."); 1110 } else if (uid.equals(DESCRIPTOR_UUID)) { 1111 // verify 1112 if (Arrays.equals(WRITE_VALUE.getBytes(), descriptor.getValue())) { 1113 notifyDescriptorWrite(new String(descriptor.getValue())); 1114 } else { 1115 notifyError("Written data is not correct"); 1116 } 1117 } else if (uid.equals(DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID)) { 1118 notifyDescriptorWriteNeedEncrypted(new String(descriptor.getValue())); 1119 } 1120 } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) { 1121 if (uid.equals(DESCRIPTOR_NO_WRITE_UUID)) { 1122 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), BleServerService.DESCRIPTOR_WRITE_NO_PERMISSION); 1123 notifyDescriptorWriteNoPermission(); 1124 } else { 1125 notifyError("Not Permission Write: " + status + " : " + descriptor.getUuid()); 1126 } 1127 } else { 1128 notifyError("Failed to write descriptor"); 1129 } 1130 } 1131 1132 @Override 1133 public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { 1134 if (DEBUG) { 1135 Log.d(TAG, "onDescriptorRead"); 1136 } 1137 1138 UUID uid = descriptor.getUuid(); 1139 if ((status == BluetoothGatt.GATT_SUCCESS)) { 1140 if ((uid != null) && (uid.equals(DESCRIPTOR_UUID))) { 1141 // verify 1142 if (Arrays.equals(BleServerService.WRITE_VALUE.getBytes(), descriptor.getValue())) { 1143 notifyDescriptorRead(new String(descriptor.getValue())); 1144 } else { 1145 notifyError("Read data is not correct"); 1146 } 1147 } else if (uid.equals(DESCRIPTOR_NEED_ENCRYPTED_READ_UUID)) { 1148 notifyDescriptorReadNeedEncrypted(new String(descriptor.getValue())); 1149 } 1150 } else if (status == BluetoothGatt.GATT_READ_NOT_PERMITTED) { 1151 if (uid.equals(DESCRIPTOR_NO_READ_UUID)) { 1152 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), BleServerService.DESCRIPTOR_READ_NO_PERMISSION); 1153 notifyDescriptorReadNoPermission(); 1154 } else { 1155 notifyError("Not Permission Read: " + status + " : " + descriptor.getUuid()); 1156 } 1157 } else { 1158 notifyError("Failed to read descriptor: " + status); 1159 } 1160 } 1161 1162 @Override 1163 public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { 1164 UUID uid = characteristic.getUuid(); 1165 if (DEBUG) { 1166 Log.d(TAG, "onCharacteristicChanged: " + uid); 1167 } 1168 if (uid != null) { 1169 if (uid.equals(INDICATE_CHARACTERISTIC_UUID)) { 1170 setNotification(characteristic, false); 1171 notifyCharacteristicIndicated(); 1172 } else { 1173 mNotifyCount--; 1174 setNotification(characteristic, false); 1175 if (mNotifyCount == 0) { 1176 notifyCharacteristicChanged(); 1177 } 1178 } 1179 } 1180 } 1181 1182 @Override 1183 public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { 1184 if (DEBUG) { 1185 Log.d(TAG, "onReliableWriteComplete: " + status); 1186 } 1187 1188 if (mExecReliableWrite != ReliableWriteState.RELIABLE_WRITE_NONE) { 1189 if (status == BluetoothGatt.GATT_SUCCESS) { 1190 notifyReliableWriteCompleted(); 1191 } else { 1192 notifyError("Failed to complete reliable write: " + status); 1193 } 1194 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 1195 } 1196 } 1197 1198 @Override 1199 public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { 1200 if (DEBUG) { 1201 Log.d(TAG, "onReadRemoteRssi"); 1202 } 1203 if (status == BluetoothGatt.GATT_SUCCESS) { 1204 notifyReadRemoteRssi(rssi); 1205 } else { 1206 notifyError("Failed to read remote rssi"); 1207 } 1208 } 1209 }; 1210 1211 private final ScanCallback mScanCallback = new ScanCallback() { 1212 @Override 1213 public void onScanResult(int callbackType, ScanResult result) { 1214 if (mBluetoothGatt == null) { 1215 // verify the validity of the advertisement packet. 1216 mValidityService = false; 1217 List<ParcelUuid> uuids = result.getScanRecord().getServiceUuids(); 1218 for (ParcelUuid uuid : uuids) { 1219 if (uuid.getUuid().equals(BleServerService.ADV_SERVICE_UUID)) { 1220 mValidityService = true; 1221 break; 1222 } 1223 } 1224 if (mValidityService) { 1225 stopScan(); 1226 1227 BluetoothDevice device = result.getDevice(); 1228 if (mSecure) { 1229 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { 1230 if (!device.createBond()) { 1231 notifyError("Failed to call create bond"); 1232 } 1233 } else { 1234 mBluetoothGatt = connectGatt(result.getDevice(), mContext, false, mSecure, mGattCallbacks); 1235 } 1236 } else { 1237 mBluetoothGatt = connectGatt(result.getDevice(), mContext, false, mSecure, mGattCallbacks); 1238 } 1239 } else { 1240 notifyError("There is no validity to Advertise servie."); 1241 } 1242 } 1243 } 1244 }; 1245 startScan()1246 private void startScan() { 1247 if (DEBUG) Log.d(TAG, "startScan"); 1248 List<ScanFilter> filter = Arrays.asList(new ScanFilter.Builder().setServiceUuid( 1249 new ParcelUuid(BleServerService.ADV_SERVICE_UUID)).build()); 1250 ScanSettings setting = new ScanSettings.Builder() 1251 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 1252 mScanner.startScan(filter, setting, mScanCallback); 1253 } 1254 stopScan()1255 private void stopScan() { 1256 if (DEBUG) Log.d(TAG, "stopScan"); 1257 if (mScanner != null) { 1258 mScanner.stopScan(mScanCallback); 1259 } 1260 } 1261 createTestData(int length)1262 private static String createTestData(int length) { 1263 StringBuilder builder = new StringBuilder(); 1264 builder.append("REQUEST_MTU"); 1265 int len = length - builder.length(); 1266 for (int i = 0; i < len; ++i) { 1267 builder.append(""+(i%10)); 1268 } 1269 return builder.toString(); 1270 } 1271 1272 private final BroadcastReceiver mBondStatusReceiver = new BroadcastReceiver() { 1273 @Override 1274 public void onReceive(Context context, Intent intent) { 1275 if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) { 1276 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 1277 int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE); 1278 switch (state) { 1279 case BluetoothDevice.BOND_BONDED: 1280 mBluetoothGatt = connectGatt(device, mContext, false, mSecure, mGattCallbacks); 1281 break; 1282 case BluetoothDevice.BOND_NONE: 1283 notifyError("Failed to create bond."); 1284 break; 1285 case BluetoothDevice.BOND_BONDING: 1286 default: // fall through 1287 // wait for next state 1288 break; 1289 } 1290 } 1291 } 1292 }; 1293 } 1294