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