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 static android.content.Context.RECEIVER_EXPORTED; 20 21 import android.app.Service; 22 import android.bluetooth.BluetoothAdapter; 23 import android.bluetooth.BluetoothDevice; 24 import android.bluetooth.BluetoothGatt; 25 import android.bluetooth.BluetoothGattCallback; 26 import android.bluetooth.BluetoothGattCharacteristic; 27 import android.bluetooth.BluetoothGattDescriptor; 28 import android.bluetooth.BluetoothGattService; 29 import android.bluetooth.BluetoothManager; 30 import android.bluetooth.BluetoothProfile; 31 import android.bluetooth.le.BluetoothLeScanner; 32 import android.bluetooth.le.ScanCallback; 33 import android.bluetooth.le.ScanFilter; 34 import android.bluetooth.le.ScanResult; 35 import android.bluetooth.le.ScanSettings; 36 import android.content.BroadcastReceiver; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.content.IntentFilter; 40 import android.os.Build; 41 import android.os.Handler; 42 import android.os.IBinder; 43 import android.os.ParcelUuid; 44 import android.text.TextUtils; 45 import android.util.Log; 46 import android.widget.Toast; 47 48 import com.android.cts.verifier.R; 49 50 import java.util.Arrays; 51 import java.util.List; 52 import java.util.Set; 53 import java.util.UUID; 54 55 public class BleClientService extends Service { 56 57 public static final boolean DEBUG = true; 58 public static final String TAG = "BleClientService"; 59 60 // Android N (2016 July 15, currently) BluetoothGatt#disconnect() does not work correct. 61 // (termination signal will not be sent) 62 // This flag switches to turn Bluetooth off instead of BluetoothGatt#disconnect(). 63 // If true, test will turn Bluetooth off. Otherwise, will call BluetoothGatt#disconnect(). 64 public static final boolean DISCONNECT_BY_TURN_BT_OFF_ON = 65 (Build.VERSION.SDK_INT > Build.VERSION_CODES.M); 66 67 // for Version 1 test 68 // private static final int TRANSPORT_MODE_FOR_SECURE_CONNECTION = BluetoothDevice 69 // .TRANSPORT_AUTO; 70 // for Version 2 test 71 private static final int TRANSPORT_MODE_FOR_SECURE_CONNECTION = BluetoothDevice.TRANSPORT_LE; 72 73 public static final int COMMAND_CONNECT = 0; 74 public static final int COMMAND_DISCONNECT = 1; 75 public static final int COMMAND_DISCOVER_SERVICE = 2; 76 public static final int COMMAND_READ_RSSI = 3; 77 public static final int COMMAND_WRITE_CHARACTERISTIC = 4; 78 public static final int COMMAND_WRITE_CHARACTERISTIC_BAD_RESP = 5; 79 public static final int COMMAND_READ_CHARACTERISTIC = 6; 80 public static final int COMMAND_WRITE_DESCRIPTOR = 7; 81 public static final int COMMAND_READ_DESCRIPTOR = 8; 82 public static final int COMMAND_SET_NOTIFICATION = 9; 83 public static final int COMMAND_BEGIN_WRITE = 10; 84 public static final int COMMAND_EXECUTE_WRITE = 11; 85 public static final int COMMAND_ABORT_RELIABLE = 12; 86 public static final int COMMAND_SCAN_START = 13; 87 public static final int COMMAND_SCAN_STOP = 14; 88 89 public static final String BLE_BLUETOOTH_MISMATCH_SECURE = 90 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_MISMATCH_SECURE"; 91 public static final String BLE_BLUETOOTH_MISMATCH_INSECURE = 92 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_MISMATCH_INSECURE"; 93 public static final String BLE_BLUETOOTH_DISABLED = 94 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_DISABLED"; 95 public static final String BLE_BLUETOOTH_CONNECTED = 96 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_CONNECTED"; 97 public static final String BLE_BLUETOOTH_DISCONNECTED = 98 "com.android.cts.verifier.bluetooth.BLE_BLUETOOTH_DISCONNECTED"; 99 public static final String BLE_SERVICES_DISCOVERED = 100 "com.android.cts.verifier.bluetooth.BLE_SERVICES_DISCOVERED"; 101 public static final String BLE_MTU_CHANGED_23BYTES = 102 "com.android.cts.verifier.bluetooth.BLE_MTU_CHANGED_23BYTES"; 103 public static final String BLE_MTU_CHANGED_512BYTES = 104 "com.android.cts.verifier.bluetooth.BLE_MTU_CHANGED_512BYTES"; 105 public static final String BLE_CHARACTERISTIC_READ = 106 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ"; 107 public static final String BLE_CHARACTERISTIC_WRITE = 108 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE"; 109 public static final String BLE_CHARACTERISTIC_CHANGED = 110 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_CHANGED"; 111 public static final String BLE_CHARACTERISTIC_INDICATED = 112 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_INDICATED"; 113 public static final String BLE_DESCRIPTOR_READ = 114 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ"; 115 public static final String BLE_DESCRIPTOR_WRITE = 116 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE"; 117 public static final String BLE_RELIABLE_WRITE_COMPLETED = 118 "com.android.cts.verifier.bluetooth.BLE_RELIABLE_WRITE_COMPLETED"; 119 public static final String BLE_RELIABLE_WRITE_BAD_RESP_COMPLETED = 120 "com.android.cts.verifier.bluetooth.BLE_RELIABLE_WRITE_BAD_RESP_COMPLETED"; 121 public static final String BLE_READ_REMOTE_RSSI = 122 "com.android.cts.verifier.bluetooth.BLE_READ_REMOTE_RSSI"; 123 public static final String BLE_PHY_READ = 124 "com.android.cts.verifier.bluetooth.BLE_PHY_READ"; 125 public static final String BLE_PHY_READ_SKIPPED = 126 "com.android.cts.verifier.bluetooth.BLE_PHY_READ_SKIPPED"; 127 public static final String BLE_PHY_UPDATE = 128 "com.android.cts.verifier.bluetooth.BLE_PHY_UPDATE"; 129 public static final String BLE_PHY_UPDATE_SKIPPED = 130 "com.android.cts.verifier.bluetooth.BLE_PHY_UPDATE_SKIPPED"; 131 public static final String BLE_ON_SERVICE_CHANGED = 132 "com.android.cts.verifier.bluetooth.BLE_ON_SERVICE_CHANGED"; 133 public static final String BLE_CHARACTERISTIC_READ_NOPERMISSION = 134 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ_NOPERMISSION"; 135 public static final String BLE_CHARACTERISTIC_WRITE_NOPERMISSION = 136 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE_NOPERMISSION"; 137 public static final String BLE_DESCRIPTOR_READ_NOPERMISSION = 138 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ_NOPERMISSION"; 139 public static final String BLE_DESCRIPTOR_WRITE_NOPERMISSION = 140 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE_NOPERMISSION"; 141 public static final String BLE_CHARACTERISTIC_READ_NEED_ENCRYPTED = 142 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_READ_NEED_ENCRYPTED"; 143 public static final String BLE_CHARACTERISTIC_WRITE_NEED_ENCRYPTED = 144 "com.android.cts.verifier.bluetooth.BLE_CHARACTERISTIC_WRITE_NEED_ENCRYPTED"; 145 public static final String BLE_DESCRIPTOR_READ_NEED_ENCRYPTED = 146 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_READ_NEED_ENCRYPTED"; 147 public static final String BLE_DESCRIPTOR_WRITE_NEED_ENCRYPTED = 148 "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE_NEED_ENCRYPTED"; 149 public static final String BLE_CLIENT_ERROR = 150 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ERROR"; 151 152 public static final String EXTRA_COMMAND = 153 "com.android.cts.verifier.bluetooth.EXTRA_COMMAND"; 154 public static final String EXTRA_WRITE_VALUE = 155 "com.android.cts.verifier.bluetooth.EXTRA_WRITE_VALUE"; 156 public static final String EXTRA_BOOL = 157 "com.android.cts.verifier.bluetooth.EXTRA_BOOL"; 158 159 160 // Literal for Client Action 161 public static final String BLE_CLIENT_ACTION_CLIENT_CONNECT = 162 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_CLIENT_CONNECT"; 163 public static final String BLE_CLIENT_ACTION_CLIENT_CONNECT_SECURE = 164 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_CLIENT_CONNECT_SECURE"; 165 public static final String BLE_CLIENT_ACTION_BLE_DISCOVER_SERVICE = 166 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_BLE_DISCOVER_SERVICE"; 167 public static final String BLE_CLIENT_ACTION_REQUEST_MTU_23 = 168 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_REQUEST_MTU_23"; 169 public static final String BLE_CLIENT_ACTION_REQUEST_MTU_512 = 170 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_REQUEST_MTU_512"; 171 public static final String BLE_CLIENT_ACTION_READ_CHARACTERISTIC = 172 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_CHARACTERISTIC"; 173 public static final String BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC = 174 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC"; 175 public static final String BLE_CLIENT_ACTION_RELIABLE_WRITE = 176 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_RELIABLE_WRITE"; 177 public static final String BLE_CLIENT_ACTION_RELIABLE_WRITE_BAD_RESP = 178 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_RELIABLE_WRITE_BAD_RESP"; 179 public static final String BLE_CLIENT_ACTION_NOTIFY_CHARACTERISTIC = 180 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_NOTIFY_CHARACTERISTIC"; 181 public static final String BLE_CLIENT_ACTION_INDICATE_CHARACTERISTIC = 182 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_INDICATE_CHARACTERISTIC"; 183 public static final String BLE_CLIENT_ACTION_READ_DESCRIPTOR = 184 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_DESCRIPTOR"; 185 public static final String BLE_CLIENT_ACTION_WRITE_DESCRIPTOR = 186 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_WRITE_DESCRIPTOR"; 187 public static final String BLE_CLIENT_ACTION_READ_RSSI = 188 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_RSSI"; 189 public static final String BLE_CLIENT_ACTION_READ_PHY = 190 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_PHY"; 191 public static final String BLE_CLIENT_ACTION_SET_PREFERRED_PHY = 192 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_SET_PREFERRED_PHY"; 193 public static final String BLE_CLIENT_ACTION_TRIGGER_SERVICE_CHANGED = 194 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_TRIGGER_SERVICE_CHANGED"; 195 public static final String BLE_CLIENT_ACTION_CLIENT_DISCONNECT = 196 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_CLIENT_DISCONNECT"; 197 public static final String BLE_CLIENT_ACTION_READ_CHARACTERISTIC_NO_PERMISSION = 198 "com.android.cts.verifier.bluetooth" 199 + ".BLE_CLIENT_ACTION_READ_CHARACTERISTIC_NO_PERMISSION"; 200 public static final String BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC_NO_PERMISSION = 201 "com.android.cts.verifier.bluetooth" 202 + ".BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC_NO_PERMISSION"; 203 public static final String BLE_CLIENT_ACTION_READ_DESCRIPTOR_NO_PERMISSION = 204 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_DESCRIPTOR_NO_PERMISSION"; 205 public static final String BLE_CLIENT_ACTION_WRITE_DESCRIPTOR_NO_PERMISSION = 206 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_WRITE_DESCRIPTOR_NO_PERMISSION"; 207 public static final String BLE_CLIENT_ACTION_READ_AUTHENTICATED_CHARACTERISTIC = 208 "com.android.cts.verifier.bluetooth" 209 + ".BLE_CLIENT_ACTION_READ_AUTHENTICATED_CHARACTERISTIC"; 210 public static final String BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_CHARACTERISTIC = 211 "com.android.cts.verifier.bluetooth" 212 + ".BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_CHARACTERISTIC"; 213 public static final String BLE_CLIENT_ACTION_READ_AUTHENTICATED_DESCRIPTOR = 214 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_READ_AUTHENTICATED_DESCRIPTOR"; 215 public static final String BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_DESCRIPTOR = 216 "com.android.cts.verifier.bluetooth.BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_DESCRIPTOR"; 217 218 public static final String EXTRA_CHARACTERISTIC_VALUE = 219 "com.android.cts.verifier.bluetooth.EXTRA_CHARACTERISTIC_VALUE"; 220 public static final String EXTRA_DESCRIPTOR_VALUE = 221 "com.android.cts.verifier.bluetooth.EXTRA_DESCRIPTOR_VALUE"; 222 public static final String EXTRA_RSSI_VALUE = 223 "com.android.cts.verifier.bluetooth.EXTRA_RSSI_VALUE"; 224 public static final String EXTRA_TX_PHY_VALUE = 225 "com.android.cts.verifier.bluetooth.EXTRA_TX_PHY_VALUE"; 226 public static final String EXTRA_RX_PHY_VALUE = 227 "com.android.cts.verifier.bluetooth.EXTRA_RX_PHY_VALUE"; 228 public static final String EXTRA_ERROR_MESSAGE = 229 "com.android.cts.verifier.bluetooth.EXTRA_ERROR_MESSAGE"; 230 231 public static final String WRITE_VALUE_512BYTES_FOR_MTU = 232 createTestData("REQUEST_MTU", 512); 233 public static final String WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE = 234 createTestData("RELIABLE_WRITE", 507); 235 236 private static final UUID SERVICE_UUID = 237 UUID.fromString("00009999-0000-1000-8000-00805f9b34fb"); 238 private static final UUID CHARACTERISTIC_UUID = 239 UUID.fromString("00009998-0000-1000-8000-00805f9b34fb"); 240 private static final UUID CHARACTERISTIC_RESULT_UUID = 241 UUID.fromString("00009974-0000-1000-8000-00805f9b34fb"); 242 private static final UUID UPDATE_CHARACTERISTIC_UUID = 243 UUID.fromString("00009997-0000-1000-8000-00805f9b34fb"); 244 private static final UUID DESCRIPTOR_UUID = 245 UUID.fromString("00009996-0000-1000-8000-00805f9b34fb"); 246 247 private static final UUID SERVICE_UUID_ADDITIONAL = 248 UUID.fromString("00009995-0000-1000-8000-00805f9b34fb"); 249 250 // Literal for registration permission of Characteristic 251 private static final UUID CHARACTERISTIC_NO_READ_UUID = 252 UUID.fromString("00009984-0000-1000-8000-00805f9b34fb"); 253 private static final UUID CHARACTERISTIC_NO_WRITE_UUID = 254 UUID.fromString("00009983-0000-1000-8000-00805f9b34fb"); 255 private static final UUID CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID = 256 UUID.fromString("00009982-0000-1000-8000-00805f9b34fb"); 257 private static final UUID CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID = 258 UUID.fromString("00009981-0000-1000-8000-00805f9b34fb"); 259 260 // Literal for registration permission of Descriptor 261 private static final UUID DESCRIPTOR_NO_READ_UUID = 262 UUID.fromString("00009973-0000-1000-8000-00805f9b34fb"); 263 private static final UUID DESCRIPTOR_NO_WRITE_UUID = 264 UUID.fromString("00009972-0000-1000-8000-00805f9b34fb"); 265 private static final UUID DESCRIPTOR_NEED_ENCRYPTED_READ_UUID = 266 UUID.fromString("00009969-0000-1000-8000-00805f9b34fb"); 267 private static final UUID DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID = 268 UUID.fromString("00009968-0000-1000-8000-00805f9b34fb"); 269 270 // Literal for registration upper limit confirmation of Characteristic 271 private static final UUID UPDATE_CHARACTERISTIC_UUID_1 = 272 UUID.fromString("00009989-0000-1000-8000-00805f9b34fb"); 273 private static final UUID UPDATE_CHARACTERISTIC_UUID_2 = 274 UUID.fromString("00009988-0000-1000-8000-00805f9b34fb"); 275 private static final UUID UPDATE_CHARACTERISTIC_UUID_3 = 276 UUID.fromString("00009987-0000-1000-8000-00805f9b34fb"); 277 private static final UUID UPDATE_CHARACTERISTIC_UUID_4 = 278 UUID.fromString("00009986-0000-1000-8000-00805f9b34fb"); 279 private static final UUID UPDATE_CHARACTERISTIC_UUID_5 = 280 UUID.fromString("00009985-0000-1000-8000-00805f9b34fb"); 281 private static final UUID UPDATE_CHARACTERISTIC_UUID_6 = 282 UUID.fromString("00009979-0000-1000-8000-00805f9b34fb"); 283 private static final UUID UPDATE_CHARACTERISTIC_UUID_7 = 284 UUID.fromString("00009978-0000-1000-8000-00805f9b34fb"); 285 private static final UUID UPDATE_CHARACTERISTIC_UUID_8 = 286 UUID.fromString("00009977-0000-1000-8000-00805f9b34fb"); 287 private static final UUID UPDATE_CHARACTERISTIC_UUID_9 = 288 UUID.fromString("00009976-0000-1000-8000-00805f9b34fb"); 289 private static final UUID UPDATE_CHARACTERISTIC_UUID_10 = 290 UUID.fromString("00009975-0000-1000-8000-00805f9b34fb"); 291 private static final UUID UPDATE_CHARACTERISTIC_UUID_11 = 292 UUID.fromString("00009959-0000-1000-8000-00805f9b34fb"); 293 private static final UUID UPDATE_CHARACTERISTIC_UUID_12 = 294 UUID.fromString("00009958-0000-1000-8000-00805f9b34fb"); 295 private static final UUID UPDATE_CHARACTERISTIC_UUID_13 = 296 UUID.fromString("00009957-0000-1000-8000-00805f9b34fb"); 297 private static final UUID UPDATE_CHARACTERISTIC_UUID_14 = 298 UUID.fromString("00009956-0000-1000-8000-00805f9b34fb"); 299 private static final UUID UPDATE_CHARACTERISTIC_UUID_15 = 300 UUID.fromString("00009955-0000-1000-8000-00805f9b34fb"); 301 302 private static final UUID SERVICE_CHANGED_CONTROL_CHARACTERISTIC_UUID = 303 UUID.fromString("00009949-0000-1000-8000-00805f9b34fb"); 304 305 private static final UUID UPDATE_DESCRIPTOR_UUID = 306 UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); 307 308 private static final UUID INDICATE_CHARACTERISTIC_UUID = 309 UUID.fromString("00009971-0000-1000-8000-00805f9b34fb"); 310 311 public static final String WRITE_VALUE = "CLIENT_TEST"; 312 private static final String NOTIFY_VALUE = "NOTIFY_TEST"; 313 public static final String WRITE_VALUE_BAD_RESP = "BAD_RESP_TEST"; 314 public static final String SERVICE_CHANGED_VALUE = "CLIENT_SVC_CHG"; 315 316 // current test category 317 private String mCurrentAction; 318 319 private BluetoothManager mBluetoothManager; 320 private BluetoothAdapter mBluetoothAdapter; 321 private BluetoothDevice mDevice; 322 private BluetoothGatt mBluetoothGatt; 323 private BluetoothLeScanner mScanner; 324 private Handler mHandler; 325 private Context mContext; 326 private boolean mSecure; 327 private int mNotifyCount; 328 private boolean mValidityService; 329 private ReliableWriteState mExecReliableWrite; 330 private byte[] mBuffer; 331 private boolean mWriteAfterMtuChangeDone = false; 332 333 // Handler for communicating task with peer. 334 private TestTaskQueue mTaskQueue; 335 336 // Lock for synchronization during notification request test. 337 private final Object mRequestNotificationLock = new Object(); 338 339 // Lock for triggering service changed event on server side. 340 private final Object mServiceChangedLock = new Object(); 341 private static final int SERVICE_CHANGED_FLAG_INIT = 0x00; 342 private static final int SERVICE_CHANGED_FLAG_TRIGGER_ACTION = 0x01; 343 private static final int SERVICE_CHANGED_FLAG_ON_SERVICE_CHANGED = 0x02; 344 private static final int SERVICE_CHANGED_FLAG_ALL = 0x03; 345 private static final int SERVICE_CHANGED_FLAG_IGNORE = 0xFF; 346 private int mServiceChangedFlag; 347 348 private enum ReliableWriteState { 349 RELIABLE_WRITE_NONE, 350 RELIABLE_WRITE_WRITE_1ST_DATA, 351 RELIABLE_WRITE_WRITE_2ND_DATA, 352 RELIABLE_WRITE_EXECUTE, 353 RELIABLE_WRITE_BAD_RESP 354 } 355 356 @Override onCreate()357 public void onCreate() { 358 super.onCreate(); 359 360 registerReceiver( 361 mBondStatusReceiver, 362 new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED), 363 RECEIVER_EXPORTED); 364 365 mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 366 mBluetoothAdapter = mBluetoothManager.getAdapter(); 367 mScanner = mBluetoothAdapter.getBluetoothLeScanner(); 368 mHandler = new Handler(); 369 mContext = this; 370 mNotifyCount = 0; 371 372 mTaskQueue = new TestTaskQueue(getClass().getName() + "_taskHandlerThread"); 373 } 374 375 @Override onStartCommand(final Intent intent, int flags, int startId)376 public int onStartCommand(final Intent intent, int flags, int startId) { 377 if (!mBluetoothAdapter.isEnabled()) { 378 notifyBluetoothDisabled(); 379 } else { 380 mTaskQueue.addTask(new Runnable() { 381 @Override 382 public void run() { 383 onTestFinish(intent.getAction()); 384 } 385 }, 1500); 386 } 387 return START_NOT_STICKY; 388 } 389 onTestFinish(String action)390 private void onTestFinish(String action) { 391 mCurrentAction = action; 392 if (mCurrentAction != null) { 393 switch (mCurrentAction) { 394 case BLE_CLIENT_ACTION_CLIENT_CONNECT_SECURE: 395 mSecure = true; 396 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 397 startScan(); 398 break; 399 case BLE_CLIENT_ACTION_CLIENT_CONNECT: 400 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 401 startScan(); 402 break; 403 case BLE_CLIENT_ACTION_BLE_DISCOVER_SERVICE: 404 if (mBluetoothGatt != null && mBleState == BluetoothProfile.STATE_CONNECTED) { 405 mBluetoothGatt.discoverServices(); 406 } else { 407 showMessage("Bluetooth LE not cnnected."); 408 } 409 break; 410 case BLE_CLIENT_ACTION_REQUEST_MTU_23: 411 /* Test the long write before changing MTU. 412 * Starting from Android U, MTU is set to 517, no matter what 413 * user request. To keep same test scope, send first 512 write 414 * before MTU change, so it make use of default MTU = 23. 415 * Later, requestMtu is called twice and test if MTU Exchange will 416 * execute only once over the air. 417 */ 418 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_512BYTES_FOR_MTU); 419 break; 420 case BLE_CLIENT_ACTION_REQUEST_MTU_512: // fall through 421 /* Call it twice to verify single MTU Exchange procedure over the link */ 422 requestMtu(); 423 requestMtu(); 424 break; 425 case BLE_CLIENT_ACTION_READ_CHARACTERISTIC: 426 readCharacteristic(CHARACTERISTIC_UUID); 427 break; 428 case BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC: 429 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE); 430 break; 431 case BLE_CLIENT_ACTION_RELIABLE_WRITE: 432 case BLE_CLIENT_ACTION_RELIABLE_WRITE_BAD_RESP: // fall through 433 mTaskQueue.addTask(new Runnable() { 434 @Override 435 public void run() { 436 reliableWrite(); 437 } 438 }); 439 break; 440 case BLE_CLIENT_ACTION_INDICATE_CHARACTERISTIC: 441 setNotification(INDICATE_CHARACTERISTIC_UUID, true); 442 break; 443 case BLE_CLIENT_ACTION_NOTIFY_CHARACTERISTIC: 444 // Registered the notify to characteristics in the service 445 mTaskQueue.addTask(new Runnable() { 446 @Override 447 public void run() { 448 mNotifyCount = 16; 449 setNotification(UPDATE_CHARACTERISTIC_UUID, true); 450 waitForDisableNotificationCompletion(); 451 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_1, 452 true); 453 waitForDisableNotificationCompletion(); 454 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_2, 455 true); 456 waitForDisableNotificationCompletion(); 457 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_3, 458 true); 459 waitForDisableNotificationCompletion(); 460 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_4, 461 true); 462 waitForDisableNotificationCompletion(); 463 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_5, 464 true); 465 waitForDisableNotificationCompletion(); 466 setNotification(UPDATE_CHARACTERISTIC_UUID_6, true); 467 waitForDisableNotificationCompletion(); 468 setNotification(UPDATE_CHARACTERISTIC_UUID_7, true); 469 waitForDisableNotificationCompletion(); 470 setNotification(UPDATE_CHARACTERISTIC_UUID_8, true); 471 waitForDisableNotificationCompletion(); 472 setNotification(UPDATE_CHARACTERISTIC_UUID_9, true); 473 waitForDisableNotificationCompletion(); 474 setNotification(UPDATE_CHARACTERISTIC_UUID_10, true); 475 waitForDisableNotificationCompletion(); 476 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_11, 477 true); 478 waitForDisableNotificationCompletion(); 479 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_12, 480 true); 481 waitForDisableNotificationCompletion(); 482 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_13, 483 true); 484 waitForDisableNotificationCompletion(); 485 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_14, 486 true); 487 waitForDisableNotificationCompletion(); 488 setNotification(SERVICE_UUID_ADDITIONAL, UPDATE_CHARACTERISTIC_UUID_15, 489 true); 490 waitForDisableNotificationCompletion(); 491 } 492 }); 493 break; 494 case BLE_CLIENT_ACTION_READ_DESCRIPTOR: 495 readDescriptor(DESCRIPTOR_UUID); 496 break; 497 case BLE_CLIENT_ACTION_WRITE_DESCRIPTOR: 498 writeDescriptor(DESCRIPTOR_UUID, WRITE_VALUE); 499 break; 500 case BLE_CLIENT_ACTION_READ_RSSI: 501 if (mBluetoothGatt != null) { 502 mBluetoothGatt.readRemoteRssi(); 503 } 504 break; 505 case BLE_CLIENT_ACTION_CLIENT_DISCONNECT: 506 if (mBluetoothGatt != null) { 507 mBluetoothGatt.disconnect(); 508 } 509 break; 510 case BLE_CLIENT_ACTION_READ_CHARACTERISTIC_NO_PERMISSION: 511 readCharacteristic(CHARACTERISTIC_NO_READ_UUID); 512 break; 513 case BLE_CLIENT_ACTION_WRITE_CHARACTERISTIC_NO_PERMISSION: 514 writeCharacteristic(CHARACTERISTIC_NO_WRITE_UUID, WRITE_VALUE); 515 break; 516 case BLE_CLIENT_ACTION_READ_DESCRIPTOR_NO_PERMISSION: 517 readDescriptor(DESCRIPTOR_NO_READ_UUID); 518 break; 519 case BLE_CLIENT_ACTION_WRITE_DESCRIPTOR_NO_PERMISSION: 520 writeDescriptor(DESCRIPTOR_NO_WRITE_UUID, WRITE_VALUE); 521 break; 522 case BLE_CLIENT_ACTION_READ_AUTHENTICATED_CHARACTERISTIC: 523 readCharacteristic(CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID); 524 break; 525 case BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_CHARACTERISTIC: 526 writeCharacteristic(CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID, WRITE_VALUE); 527 break; 528 case BLE_CLIENT_ACTION_READ_AUTHENTICATED_DESCRIPTOR: 529 readDescriptor(CHARACTERISTIC_RESULT_UUID, DESCRIPTOR_NEED_ENCRYPTED_READ_UUID); 530 break; 531 case BLE_CLIENT_ACTION_WRITE_AUTHENTICATED_DESCRIPTOR: 532 writeDescriptor(CHARACTERISTIC_RESULT_UUID, 533 DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID, WRITE_VALUE); 534 break; 535 case BLE_CLIENT_ACTION_READ_PHY: 536 if (mBluetoothGatt != null) { 537 mBluetoothGatt.readPhy(); 538 } 539 break; 540 case BLE_CLIENT_ACTION_SET_PREFERRED_PHY: 541 if (mBluetoothGatt != null) { 542 mBluetoothGatt.setPreferredPhy(BluetoothDevice.PHY_LE_1M_MASK, 543 BluetoothDevice.PHY_LE_1M_MASK, 544 BluetoothDevice.PHY_OPTION_NO_PREFERRED); 545 } 546 break; 547 case BLE_CLIENT_ACTION_TRIGGER_SERVICE_CHANGED: 548 initializeServiceChangedEvent(); 549 writeCharacteristic(SERVICE_CHANGED_CONTROL_CHARACTERISTIC_UUID, WRITE_VALUE); 550 break; 551 } 552 } 553 } 554 555 @Override onBind(Intent intent)556 public IBinder onBind(Intent intent) { 557 return null; 558 } 559 560 @Override onDestroy()561 public void onDestroy() { 562 super.onDestroy(); 563 if (mBluetoothGatt != null) { 564 mBluetoothGatt.disconnect(); 565 mBluetoothGatt.close(); 566 mBluetoothGatt = null; 567 } 568 stopScan(); 569 unregisterReceiver(mBondStatusReceiver); 570 571 mTaskQueue.quit(); 572 } 573 574 /** 575 * Connect to GATT Server hosted by this device. Caller acts as GATT client. 576 * The callback is used to deliver results to Caller, such as connection status as well 577 * as any further GATT client operations. 578 * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct 579 * GATT client operations. 580 * 581 * @param callback GATT callback handler that will receive asynchronous callbacks. 582 * @param autoConnect Whether to directly connect to the remote device (false) or to 583 * automatically connect as soon as the remote device becomes available (true). 584 * @param isSecure Whether to use transport mode for secure connection (true or false) 585 * @throws IllegalArgumentException if callback is null 586 */ connectGatt(BluetoothDevice device, Context context, boolean autoConnect, boolean isSecure, BluetoothGattCallback callback)587 public static BluetoothGatt connectGatt(BluetoothDevice device, Context context, 588 boolean autoConnect, boolean isSecure, BluetoothGattCallback callback) { 589 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 590 if (isSecure) { 591 if (TRANSPORT_MODE_FOR_SECURE_CONNECTION == BluetoothDevice.TRANSPORT_AUTO) { 592 Toast.makeText(context, "connectGatt(transport=AUTO)", 593 Toast.LENGTH_SHORT).show(); 594 } else { 595 Toast.makeText(context, "connectGatt(transport=LE)", Toast.LENGTH_SHORT).show(); 596 } 597 return device.connectGatt(context, autoConnect, callback, 598 TRANSPORT_MODE_FOR_SECURE_CONNECTION); 599 } else { 600 Toast.makeText(context, "connectGatt(transport=LE)", Toast.LENGTH_SHORT).show(); 601 return device.connectGatt(context, autoConnect, callback, 602 BluetoothDevice.TRANSPORT_LE); 603 } 604 } else { 605 Toast.makeText(context, "connectGatt", Toast.LENGTH_SHORT).show(); 606 return device.connectGatt(context, autoConnect, callback); 607 } 608 } 609 requestMtu()610 private void requestMtu() { 611 if (mBluetoothGatt != null) { 612 // MTU request test does not work on Android 6.0 in secure mode. 613 // (BluetoothDevice#createBond() does not work on Android 6.0. 614 // So devices can't establish Bluetooth LE pairing.) 615 boolean mtuTestExecutable = true; 616 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) { 617 mtuTestExecutable = !mSecure; 618 } 619 620 if (mtuTestExecutable) { 621 int mtu = 0; 622 if (BLE_CLIENT_ACTION_REQUEST_MTU_23.equals(mCurrentAction)) { 623 mtu = 23; 624 } else if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction)) { 625 mtu = 512; 626 } else { 627 throw new IllegalStateException("unexpected action: " + mCurrentAction); 628 } 629 mBluetoothGatt.requestMtu(mtu); 630 } else { 631 showMessage("Skip MTU test."); 632 notifyMtuChanged(); 633 } 634 } 635 } 636 writeCharacteristic(BluetoothGattCharacteristic characteristic, String writeValue)637 private void writeCharacteristic(BluetoothGattCharacteristic characteristic, 638 String writeValue) { 639 if (characteristic != null) { 640 // Note: setValue() should not be necessary when using writeCharacteristic(byte[]) which 641 // is added on Android T, but here we call the method in order to make the test 642 // easier to read. Otherwise, we should verify the written value by calling 643 // readCharacteristic() but that makes the whole test hard to read. 644 characteristic.setValue(writeValue); 645 mBluetoothGatt.writeCharacteristic(characteristic, writeValue.getBytes(), 646 characteristic.getWriteType()); 647 } 648 } 649 writeCharacteristic(UUID uid, String writeValue)650 private void writeCharacteristic(UUID uid, String writeValue) { 651 BluetoothGattCharacteristic characteristic = getCharacteristic(uid); 652 if (characteristic != null) { 653 writeCharacteristic(characteristic, writeValue); 654 } 655 } 656 readCharacteristic(UUID uuid)657 private void readCharacteristic(UUID uuid) { 658 BluetoothGattCharacteristic characteristic = getCharacteristic(uuid); 659 if (characteristic != null) { 660 mBluetoothGatt.readCharacteristic(characteristic); 661 } 662 } 663 writeDescriptor(UUID uid, String writeValue)664 private void writeDescriptor(UUID uid, String writeValue) { 665 BluetoothGattDescriptor descriptor = getDescriptor(uid); 666 if (descriptor != null) { 667 // Note: setValue() should not be necessary when using writeDescriptor(byte[]) which 668 // is added on Android T, but here we call the method in order to make the test 669 // easier to read. Otherwise, we should verify the written value by calling 670 // readDescriptor() but that makes the whole test hard to read. 671 descriptor.setValue(writeValue.getBytes()); 672 mBluetoothGatt.writeDescriptor(descriptor, writeValue.getBytes()); 673 } 674 } 675 readDescriptor(UUID uuid)676 private void readDescriptor(UUID uuid) { 677 BluetoothGattDescriptor descriptor = getDescriptor(uuid); 678 if (descriptor != null) { 679 mBluetoothGatt.readDescriptor(descriptor); 680 } 681 } 682 writeDescriptor(UUID cuid, UUID duid, String writeValue)683 private void writeDescriptor(UUID cuid, UUID duid, String writeValue) { 684 BluetoothGattDescriptor descriptor = getDescriptor(cuid, duid); 685 if (descriptor != null) { 686 // Note: setValue() should not be necessary when using writeDescriptor(byte[]) which 687 // is added on Android T, but here we call the method in order to make the test 688 // easier to read. Otherwise, we should verify the written value by calling 689 // readDescriptor() but that makes the whole test hard to read. 690 descriptor.setValue(writeValue.getBytes()); 691 mBluetoothGatt.writeDescriptor(descriptor, writeValue.getBytes()); 692 } 693 } 694 readDescriptor(UUID cuid, UUID duid)695 private void readDescriptor(UUID cuid, UUID duid) { 696 BluetoothGattDescriptor descriptor = getDescriptor(cuid, duid); 697 if (descriptor != null) { 698 mBluetoothGatt.readDescriptor(descriptor); 699 } 700 } 701 notifyDisableNotificationCompletion()702 private void notifyDisableNotificationCompletion() { 703 synchronized (mRequestNotificationLock) { 704 mRequestNotificationLock.notify(); 705 } 706 } 707 waitForDisableNotificationCompletion()708 private void waitForDisableNotificationCompletion() { 709 synchronized (mRequestNotificationLock) { 710 try { 711 mRequestNotificationLock.wait(); 712 } catch (InterruptedException e) { 713 Log.e(TAG, "Error in waitForDisableNotificationCompletion" + e); 714 } 715 } 716 } 717 initializeServiceChangedEvent()718 private void initializeServiceChangedEvent() { 719 synchronized (mServiceChangedLock) { 720 mServiceChangedFlag = SERVICE_CHANGED_FLAG_INIT; 721 } 722 } 723 sendServiceChangedEventIfReady(int flag)724 private void sendServiceChangedEventIfReady(int flag) { 725 boolean shouldSend = false; 726 synchronized (mServiceChangedLock) { 727 mServiceChangedFlag |= flag; 728 if (mServiceChangedFlag == SERVICE_CHANGED_FLAG_ALL) { 729 mServiceChangedFlag |= SERVICE_CHANGED_FLAG_IGNORE; 730 shouldSend = true; 731 } 732 } 733 734 if (shouldSend) { 735 // This is to send result to the connected GATT server. 736 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), 737 SERVICE_CHANGED_VALUE); 738 } 739 } 740 setNotification(BluetoothGattCharacteristic characteristic, boolean enable)741 private void setNotification(BluetoothGattCharacteristic characteristic, boolean enable) { 742 if (characteristic != null) { 743 mBluetoothGatt.setCharacteristicNotification(characteristic, enable); 744 BluetoothGattDescriptor descriptor = characteristic.getDescriptor( 745 UPDATE_DESCRIPTOR_UUID); 746 if (enable) { 747 if (characteristic.getUuid().equals(INDICATE_CHARACTERISTIC_UUID)) { 748 descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE); 749 } else { 750 descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); 751 } 752 } else { 753 descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 754 } 755 mBluetoothGatt.writeDescriptor(descriptor); 756 } 757 } 758 setNotification(UUID serviceUid, UUID characteristicUid, boolean enable)759 private void setNotification(UUID serviceUid, UUID characteristicUid, boolean enable) { 760 BluetoothGattCharacteristic characteristic = getCharacteristic(serviceUid, 761 characteristicUid); 762 if (characteristic != null) { 763 setNotification(characteristic, enable); 764 } 765 } 766 setNotification(UUID uid, boolean enable)767 private void setNotification(UUID uid, boolean enable) { 768 BluetoothGattCharacteristic characteristic = getCharacteristic(uid); 769 if (characteristic != null) { 770 setNotification(characteristic, enable); 771 } 772 } 773 notifyError(String message)774 private void notifyError(String message) { 775 showMessage(message); 776 Log.i(TAG, message); 777 778 Intent intent = new Intent(BLE_CLIENT_ERROR); 779 sendBroadcast(intent); 780 } 781 notifyMismatchSecure()782 private void notifyMismatchSecure() { 783 Intent intent = new Intent(BLE_BLUETOOTH_MISMATCH_SECURE); 784 sendBroadcast(intent); 785 } 786 notifyMismatchInsecure()787 private void notifyMismatchInsecure() { 788 Intent intent = new Intent(BLE_BLUETOOTH_MISMATCH_INSECURE); 789 sendBroadcast(intent); 790 } 791 notifyBluetoothDisabled()792 private void notifyBluetoothDisabled() { 793 Intent intent = new Intent(BLE_BLUETOOTH_DISABLED); 794 sendBroadcast(intent); 795 } 796 notifyConnected()797 private void notifyConnected() { 798 showMessage("Bluetooth LE connected"); 799 Intent intent = new Intent(BLE_BLUETOOTH_CONNECTED); 800 sendBroadcast(intent); 801 } 802 notifyDisconnected()803 private void notifyDisconnected() { 804 showMessage("Bluetooth LE disconnected"); 805 Intent intent = new Intent(BLE_BLUETOOTH_DISCONNECTED); 806 sendBroadcast(intent); 807 } 808 notifyServicesDiscovered()809 private void notifyServicesDiscovered() { 810 showMessage("Service discovered"); 811 Intent intent = new Intent(BLE_SERVICES_DISCOVERED); 812 sendBroadcast(intent); 813 } 814 notifyMtuChanged()815 private void notifyMtuChanged() { 816 Intent intent; 817 if (BLE_CLIENT_ACTION_REQUEST_MTU_23.equals(mCurrentAction)) { 818 intent = new Intent(BLE_MTU_CHANGED_23BYTES); 819 } else if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction)) { 820 intent = new Intent(BLE_MTU_CHANGED_512BYTES); 821 } else { 822 throw new IllegalStateException("unexpected action: " + mCurrentAction); 823 } 824 sendBroadcast(intent); 825 } 826 notifyCharacteristicRead(String value)827 private void notifyCharacteristicRead(String value) { 828 showMessage("Characteristic read: " + value); 829 Intent intent = new Intent(BLE_CHARACTERISTIC_READ); 830 intent.putExtra(EXTRA_CHARACTERISTIC_VALUE, value); 831 sendBroadcast(intent); 832 } 833 notifyCharacteristicWrite(String value)834 private void notifyCharacteristicWrite(String value) { 835 showMessage("Characteristic write: " + value); 836 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE); 837 sendBroadcast(intent); 838 } 839 notifyCharacteristicReadNoPermission()840 private void notifyCharacteristicReadNoPermission() { 841 showMessage("Characteristic not read: No Permission"); 842 Intent intent = new Intent(BLE_CHARACTERISTIC_READ_NOPERMISSION); 843 sendBroadcast(intent); 844 } 845 notifyCharacteristicWriteNoPermission(String value)846 private void notifyCharacteristicWriteNoPermission(String value) { 847 showMessage("Characteristic write: No Permission"); 848 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_NOPERMISSION); 849 sendBroadcast(intent); 850 } 851 notifyCharacteristicReadNeedEncrypted(String value)852 private void notifyCharacteristicReadNeedEncrypted(String value) { 853 showMessage("Characteristic read with encrypted: " + value); 854 Intent intent = new Intent(BLE_CHARACTERISTIC_READ_NEED_ENCRYPTED); 855 sendBroadcast(intent); 856 } 857 notifyCharacteristicWriteNeedEncrypted(String value)858 private void notifyCharacteristicWriteNeedEncrypted(String value) { 859 showMessage("Characteristic write with encrypted: " + value); 860 Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE_NEED_ENCRYPTED); 861 sendBroadcast(intent); 862 } 863 notifyCharacteristicChanged()864 private void notifyCharacteristicChanged() { 865 showMessage("Characteristic changed"); 866 Intent intent = new Intent(BLE_CHARACTERISTIC_CHANGED); 867 sendBroadcast(intent); 868 } 869 notifyCharacteristicIndicated()870 private void notifyCharacteristicIndicated() { 871 showMessage("Characteristic Indicated"); 872 Intent intent = new Intent(BLE_CHARACTERISTIC_INDICATED); 873 sendBroadcast(intent); 874 } 875 notifyDescriptorRead(String value)876 private void notifyDescriptorRead(String value) { 877 showMessage("Descriptor read: " + value); 878 Intent intent = new Intent(BLE_DESCRIPTOR_READ); 879 intent.putExtra(EXTRA_DESCRIPTOR_VALUE, value); 880 sendBroadcast(intent); 881 } 882 notifyDescriptorWrite(String value)883 private void notifyDescriptorWrite(String value) { 884 showMessage("Descriptor write: " + value); 885 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE); 886 sendBroadcast(intent); 887 } 888 notifyDescriptorReadNoPermission()889 private void notifyDescriptorReadNoPermission() { 890 showMessage("Descriptor read: No Permission"); 891 Intent intent = new Intent(BLE_DESCRIPTOR_READ_NOPERMISSION); 892 sendBroadcast(intent); 893 } 894 notifyDescriptorWriteNoPermission()895 private void notifyDescriptorWriteNoPermission() { 896 showMessage("Descriptor write: NoPermission"); 897 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_NOPERMISSION); 898 sendBroadcast(intent); 899 } 900 notifyDescriptorReadNeedEncrypted(String value)901 private void notifyDescriptorReadNeedEncrypted(String value) { 902 showMessage("Descriptor read with encrypted: " + value); 903 Intent intent = new Intent(BLE_DESCRIPTOR_READ_NEED_ENCRYPTED); 904 sendBroadcast(intent); 905 } 906 notifyDescriptorWriteNeedEncrypted(String value)907 private void notifyDescriptorWriteNeedEncrypted(String value) { 908 showMessage("Descriptor write with encrypted: " + value); 909 Intent intent = new Intent(BLE_DESCRIPTOR_WRITE_NEED_ENCRYPTED); 910 sendBroadcast(intent); 911 } 912 notifyReliableWriteCompleted()913 private void notifyReliableWriteCompleted() { 914 showMessage("Reliable write complete"); 915 Intent intent = new Intent(BLE_RELIABLE_WRITE_COMPLETED); 916 sendBroadcast(intent); 917 } 918 notifyReliableWriteBadRespCompleted(String err)919 private void notifyReliableWriteBadRespCompleted(String err) { 920 showMessage("Reliable write(bad response) complete"); 921 Intent intent = new Intent(BLE_RELIABLE_WRITE_BAD_RESP_COMPLETED); 922 if (err != null) { 923 intent.putExtra(EXTRA_ERROR_MESSAGE, err); 924 } 925 sendBroadcast(intent); 926 } 927 notifyReadRemoteRssi(int rssi)928 private void notifyReadRemoteRssi(int rssi) { 929 showMessage("Remote rssi read: " + rssi); 930 Intent intent = new Intent(BLE_READ_REMOTE_RSSI); 931 intent.putExtra(EXTRA_RSSI_VALUE, rssi); 932 sendBroadcast(intent); 933 } 934 notifyPhyRead(int txPhy, int rxPhy)935 private void notifyPhyRead(int txPhy, int rxPhy) { 936 if (BLE_CLIENT_ACTION_READ_PHY.equals(mCurrentAction)) { 937 showMessage("Phy read: txPhy=" + txPhy + ", rxPhy=" + rxPhy); 938 Intent intent = new Intent(BLE_PHY_READ); 939 intent.putExtra(EXTRA_TX_PHY_VALUE, txPhy); 940 intent.putExtra(EXTRA_RX_PHY_VALUE, rxPhy); 941 sendBroadcast(intent); 942 } else { 943 Log.d(TAG, "notifyPhyRead arrived without BLE_CLIENT_ACTION_READ_PHY"); 944 } 945 } 946 notifyPhyReadSkipped()947 private void notifyPhyReadSkipped() { 948 showMessage("Phy read not supported. Skipping the test."); 949 Intent intent = new Intent(BLE_PHY_READ_SKIPPED); 950 sendBroadcast(intent); 951 } 952 notifyPhyUpdate(int txPhy, int rxPhy)953 private void notifyPhyUpdate(int txPhy, int rxPhy) { 954 if (BLE_CLIENT_ACTION_SET_PREFERRED_PHY.equals(mCurrentAction)) { 955 showMessage("Phy update: txPhy=" + txPhy + ", rxPhy=" + rxPhy); 956 Intent intent = new Intent(BLE_PHY_UPDATE); 957 intent.putExtra(EXTRA_TX_PHY_VALUE, txPhy); 958 intent.putExtra(EXTRA_RX_PHY_VALUE, rxPhy); 959 sendBroadcast(intent); 960 } else { 961 Log.d(TAG, "notifyPhyUpdate arrived without BLE_CLIENT_ACTION_SET_PREFERRED_PHY"); 962 } 963 } 964 notifyPhyUpdateSkipped()965 private void notifyPhyUpdateSkipped() { 966 showMessage("Phy update not supported. Skipping the test."); 967 Intent intent = new Intent(BLE_PHY_UPDATE_SKIPPED); 968 sendBroadcast(intent); 969 } 970 notifyServiceChanged()971 private void notifyServiceChanged() { 972 showMessage("Remote service changed"); 973 Intent intent = new Intent(BLE_ON_SERVICE_CHANGED); 974 sendBroadcast(intent); 975 } 976 getService(UUID serverUid)977 private BluetoothGattService getService(UUID serverUid) { 978 BluetoothGattService service = null; 979 980 if (mBluetoothGatt != null) { 981 service = mBluetoothGatt.getService(serverUid); 982 if (service == null) { 983 showMessage("Service not found"); 984 } 985 } 986 return service; 987 } 988 getService()989 private BluetoothGattService getService() { 990 BluetoothGattService service = null; 991 992 if (mBluetoothGatt != null) { 993 service = mBluetoothGatt.getService(SERVICE_UUID); 994 if (service == null) { 995 showMessage("Service not found"); 996 } 997 } 998 return service; 999 } 1000 getCharacteristic(UUID serverUid, UUID characteristicUid)1001 private BluetoothGattCharacteristic getCharacteristic(UUID serverUid, UUID characteristicUid) { 1002 BluetoothGattCharacteristic characteristic = null; 1003 1004 BluetoothGattService service = getService(serverUid); 1005 if (service != null) { 1006 characteristic = service.getCharacteristic(characteristicUid); 1007 if (characteristic == null) { 1008 showMessage("Characteristic not found"); 1009 } 1010 } 1011 return characteristic; 1012 } 1013 getCharacteristic(UUID uuid)1014 private BluetoothGattCharacteristic getCharacteristic(UUID uuid) { 1015 BluetoothGattCharacteristic characteristic = null; 1016 1017 BluetoothGattService service = getService(); 1018 if (service != null) { 1019 characteristic = service.getCharacteristic(uuid); 1020 if (characteristic == null) { 1021 showMessage("Characteristic not found"); 1022 } 1023 } 1024 return characteristic; 1025 } 1026 getDescriptor(UUID uid)1027 private BluetoothGattDescriptor getDescriptor(UUID uid) { 1028 BluetoothGattDescriptor descriptor = null; 1029 1030 BluetoothGattCharacteristic characteristic = getCharacteristic(CHARACTERISTIC_UUID); 1031 if (characteristic != null) { 1032 descriptor = characteristic.getDescriptor(uid); 1033 if (descriptor == null) { 1034 showMessage("Descriptor not found"); 1035 } 1036 } 1037 return descriptor; 1038 } 1039 getDescriptor(UUID cuid, UUID duid)1040 private BluetoothGattDescriptor getDescriptor(UUID cuid, UUID duid) { 1041 BluetoothGattDescriptor descriptor = null; 1042 1043 BluetoothGattCharacteristic characteristic = getCharacteristic(cuid); 1044 if (characteristic != null) { 1045 descriptor = characteristic.getDescriptor(duid); 1046 if (descriptor == null) { 1047 showMessage("Descriptor not found"); 1048 } 1049 } 1050 return descriptor; 1051 } 1052 showMessage(final String msg)1053 private void showMessage(final String msg) { 1054 mHandler.post(new Runnable() { 1055 public void run() { 1056 Toast.makeText(BleClientService.this, msg, Toast.LENGTH_SHORT).show(); 1057 } 1058 }); 1059 } 1060 sleep(int millis)1061 private void sleep(int millis) { 1062 try { 1063 Thread.sleep(millis); 1064 } catch (InterruptedException e) { 1065 Log.e(TAG, "Error in thread sleep", e); 1066 } 1067 } 1068 reliableWrite()1069 private void reliableWrite() { 1070 // aborting test 1071 mBluetoothGatt.beginReliableWrite(); 1072 sleep(1000); 1073 mBluetoothGatt.abortReliableWrite(); 1074 1075 // writing test 1076 sleep(2000); 1077 mBluetoothGatt.beginReliableWrite(); 1078 sleep(1000); 1079 1080 if (BLE_CLIENT_ACTION_RELIABLE_WRITE.equals(mCurrentAction)) { 1081 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_WRITE_1ST_DATA; 1082 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE); 1083 } else { 1084 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_BAD_RESP; 1085 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_BAD_RESP); 1086 } 1087 } 1088 1089 private int mBleState = BluetoothProfile.STATE_DISCONNECTED; 1090 1091 private final BluetoothGattCallback mGattCallbacks = new BluetoothGattCallback() { 1092 @Override 1093 public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { 1094 super.onConnectionStateChange(gatt, status, newState); 1095 if (DEBUG) { 1096 Log.d(TAG, 1097 "onConnectionStateChange: status= " + status + ", newState= " + newState); 1098 } 1099 if (status == BluetoothGatt.GATT_SUCCESS) { 1100 if (newState == BluetoothProfile.STATE_CONNECTED) { 1101 mBleState = newState; 1102 int bond = gatt.getDevice().getBondState(); 1103 boolean bonded = false; 1104 BluetoothDevice target = gatt.getDevice(); 1105 Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices(); 1106 if (pairedDevices.size() > 0) { 1107 for (BluetoothDevice device : pairedDevices) { 1108 if (device.getAddress().equals(target.getAddress())) { 1109 bonded = true; 1110 break; 1111 } 1112 } 1113 } 1114 if (mSecure && ((bond == BluetoothDevice.BOND_NONE) || !bonded)) { 1115 // not pairing and execute Secure Test 1116 mBluetoothGatt.disconnect(); 1117 notifyMismatchSecure(); 1118 } else if (!mSecure && ((bond != BluetoothDevice.BOND_NONE) || bonded)) { 1119 // already pairing nad execute Insecure Test 1120 mBluetoothGatt.disconnect(); 1121 notifyMismatchInsecure(); 1122 } else { 1123 notifyConnected(); 1124 } 1125 } else if (status == BluetoothProfile.STATE_DISCONNECTED) { 1126 mBleState = newState; 1127 mSecure = false; 1128 mBluetoothGatt.close(); 1129 notifyDisconnected(); 1130 } 1131 } else { 1132 showMessage("Failed to connect: " + status + " , newState = " + newState); 1133 mBluetoothGatt.close(); 1134 mBluetoothGatt = null; 1135 } 1136 } 1137 1138 @Override 1139 public void onServicesDiscovered(BluetoothGatt gatt, int status) { 1140 super.onServicesDiscovered(gatt, status); 1141 if (BLE_CLIENT_ACTION_BLE_DISCOVER_SERVICE.equals(mCurrentAction)) { 1142 if (DEBUG) { 1143 Log.d(TAG, "onServiceDiscovered"); 1144 } 1145 if ((status == BluetoothGatt.GATT_SUCCESS) 1146 && (mBluetoothGatt.getService(SERVICE_UUID) != null)) { 1147 notifyServicesDiscovered(); 1148 } 1149 } else { 1150 Log.d(TAG, "onServicesDiscovered without BLE_CLIENT_ACTION_BLE_DISCOVER_SERVICE"); 1151 } 1152 } 1153 1154 @Override 1155 public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { 1156 super.onMtuChanged(gatt, mtu, status); 1157 if (DEBUG) { 1158 Log.d(TAG, "onMtuChanged"); 1159 } 1160 if (status == BluetoothGatt.GATT_SUCCESS) { 1161 // verify MTU size which now is always equal to max 517 1162 int expectedNewMtu = 517; 1163 if (mtu != expectedNewMtu) { 1164 String msg = String.format(getString(R.string.ble_mtu_mismatch_message), 1165 expectedNewMtu, mtu); 1166 showMessage(msg); 1167 } 1168 1169 if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction) 1170 && !mWriteAfterMtuChangeDone) { 1171 /* Verify write characteristic on bigger MTU */ 1172 writeCharacteristic(CHARACTERISTIC_UUID, WRITE_VALUE_512BYTES_FOR_MTU); 1173 mWriteAfterMtuChangeDone = true; 1174 } 1175 } else { 1176 notifyError("Failed to request mtu: " + status); 1177 } 1178 } 1179 1180 @Override 1181 public void onCharacteristicWrite(BluetoothGatt gatt, 1182 BluetoothGattCharacteristic characteristic, final int status) { 1183 super.onCharacteristicWrite(gatt, characteristic, status); 1184 String value = characteristic.getStringValue(0); 1185 final UUID uid = characteristic.getUuid(); 1186 if (DEBUG) { 1187 Log.d(TAG, 1188 "onCharacteristicWrite: characteristic.val=" + value + " status=" + status); 1189 } 1190 1191 if (BLE_CLIENT_ACTION_TRIGGER_SERVICE_CHANGED.equals(mCurrentAction)) { 1192 if (SERVICE_CHANGED_VALUE.equals(value)) { 1193 if (status == BluetoothGatt.GATT_SUCCESS) { 1194 // Waits until the GATT server sends the response, we can then do notify. 1195 notifyServiceChanged(); 1196 } else { 1197 notifyError("Failed to send result for service changed event"); 1198 } 1199 } else { 1200 // The reason not to check the status code is that we know there is a service 1201 // changed event coming later, sometimes the status code will be modified by 1202 // bt stack (133), but it's ok, as long as onServiceChanged is called, we then 1203 // know the request is successfully sent during this test session. 1204 sendServiceChangedEventIfReady(SERVICE_CHANGED_FLAG_TRIGGER_ACTION); 1205 } 1206 } else if (BLE_CLIENT_ACTION_REQUEST_MTU_512.equals(mCurrentAction) || 1207 BLE_CLIENT_ACTION_REQUEST_MTU_23.equals(mCurrentAction)) { 1208 if (status == BluetoothGatt.GATT_SUCCESS) { 1209 notifyMtuChanged(); 1210 } else { 1211 notifyError("Failed to write characteristic: " + status + " : " + uid); 1212 } 1213 } else { 1214 switch (mExecReliableWrite) { 1215 case RELIABLE_WRITE_NONE: 1216 if (status == BluetoothGatt.GATT_SUCCESS) { 1217 if (characteristic.getUuid().equals( 1218 CHARACTERISTIC_NEED_ENCRYPTED_WRITE_UUID)) { 1219 notifyCharacteristicWriteNeedEncrypted(value); 1220 } else if (!characteristic.getUuid().equals( 1221 CHARACTERISTIC_RESULT_UUID)) { 1222 // verify 1223 if (Arrays.equals(BleClientService.WRITE_VALUE.getBytes(), 1224 characteristic.getValue())) { 1225 notifyCharacteristicWrite(value); 1226 } else { 1227 notifyError("Written data is not correct"); 1228 } 1229 } 1230 } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) { 1231 if (uid.equals(CHARACTERISTIC_NO_WRITE_UUID)) { 1232 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), 1233 BleServerService.WRITE_NO_PERMISSION); 1234 notifyCharacteristicWriteNoPermission(value); 1235 } else { 1236 notifyError("Not Permission Write: " + status + " : " + uid); 1237 } 1238 } else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) { 1239 notifyError("Not Authentication Write: " + status + " : " + uid); 1240 } else { 1241 notifyError("Failed to write characteristic: " + status + " : " + uid); 1242 } 1243 break; 1244 case RELIABLE_WRITE_WRITE_1ST_DATA: 1245 // verify 1246 if (WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE.equals(value)) { 1247 // write next data 1248 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_WRITE_2ND_DATA; 1249 writeCharacteristic(CHARACTERISTIC_UUID, 1250 WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE); 1251 } else { 1252 notifyError("Failed to write characteristic: " + status + " : " + uid); 1253 } 1254 break; 1255 case RELIABLE_WRITE_WRITE_2ND_DATA: 1256 // verify 1257 if (WRITE_VALUE_507BYTES_FOR_RELIABLE_WRITE.equals(value)) { 1258 // execute write 1259 mTaskQueue.addTask(new Runnable() { 1260 @Override 1261 public void run() { 1262 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_EXECUTE; 1263 if (!mBluetoothGatt.executeReliableWrite()) { 1264 notifyError("reliable write failed"); 1265 } 1266 } 1267 }, 1000); 1268 } else { 1269 notifyError("Failed to write characteristic: " + status + " : " + uid); 1270 } 1271 break; 1272 case RELIABLE_WRITE_BAD_RESP: 1273 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 1274 // verify response 1275 // Server sends empty response for this test. 1276 // Response must be empty. 1277 String err = null; 1278 if (!TextUtils.isEmpty(value)) { 1279 err = "response is not empty"; 1280 showMessage(err); 1281 } 1282 // finish reliable write 1283 final String errValue = err; 1284 mTaskQueue.addTask(new Runnable() { 1285 @Override 1286 public void run() { 1287 mBluetoothGatt.abortReliableWrite(); 1288 notifyReliableWriteBadRespCompleted(errValue); 1289 } 1290 }, 1000); 1291 break; 1292 } 1293 } 1294 } 1295 1296 @Override 1297 public void onCharacteristicRead(BluetoothGatt gatt, 1298 BluetoothGattCharacteristic characteristic, int status) { 1299 super.onCharacteristicRead(gatt, characteristic, status); 1300 // Note: Both this method and onCharacteristicRead(byte[]) will be called. 1301 UUID uid = characteristic.getUuid(); 1302 if (DEBUG) { 1303 Log.d(TAG, "onCharacteristicRead (deprecated): status=" + status); 1304 } 1305 } 1306 1307 @Override 1308 public void onCharacteristicRead(BluetoothGatt gatt, 1309 BluetoothGattCharacteristic characteristic, byte[] value, int status) { 1310 super.onCharacteristicRead(gatt, characteristic, value, status); 1311 UUID uid = characteristic.getUuid(); 1312 if (DEBUG) { 1313 Log.d(TAG, "onCharacteristicRead (memory safe version): status=" + status); 1314 } 1315 1316 if (status == BluetoothGatt.GATT_SUCCESS) { 1317 String stringValue = new String(value); 1318 if (characteristic.getUuid().equals(CHARACTERISTIC_NEED_ENCRYPTED_READ_UUID)) { 1319 notifyCharacteristicReadNeedEncrypted(stringValue); 1320 } else { 1321 // verify 1322 if (BleServerService.WRITE_VALUE.equals(stringValue)) { 1323 notifyCharacteristicRead(stringValue); 1324 } else { 1325 notifyError("Read data is not correct"); 1326 } 1327 } 1328 } else if (status == BluetoothGatt.GATT_READ_NOT_PERMITTED) { 1329 if (uid.equals(CHARACTERISTIC_NO_READ_UUID)) { 1330 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), 1331 BleServerService.READ_NO_PERMISSION); 1332 notifyCharacteristicReadNoPermission(); 1333 } else { 1334 notifyError("Not Permission Read: " + status + " : " + uid); 1335 } 1336 } else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) { 1337 notifyError("Not Authentication Read: " + status + " : " + uid); 1338 } else { 1339 notifyError("Failed to read characteristic: " + status + " : " + uid); 1340 } 1341 } 1342 1343 @Override 1344 public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, 1345 int status) { 1346 super.onDescriptorWrite(gatt, descriptor, status); 1347 if (DEBUG) { 1348 Log.d(TAG, "onDescriptorWrite"); 1349 } 1350 UUID uid = descriptor.getUuid(); 1351 if ((status == BluetoothGatt.GATT_SUCCESS)) { 1352 if (uid.equals(UPDATE_DESCRIPTOR_UUID)) { 1353 Log.d(TAG, "write in update descriptor."); 1354 if (Arrays.equals(descriptor.getValue(), 1355 BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE)) { 1356 notifyDisableNotificationCompletion(); 1357 } 1358 } else if (uid.equals(DESCRIPTOR_UUID)) { 1359 // verify 1360 if (Arrays.equals(WRITE_VALUE.getBytes(), descriptor.getValue())) { 1361 notifyDescriptorWrite(new String(descriptor.getValue())); 1362 } else { 1363 notifyError("Written data is not correct"); 1364 } 1365 } else if (uid.equals(DESCRIPTOR_NEED_ENCRYPTED_WRITE_UUID)) { 1366 notifyDescriptorWriteNeedEncrypted(new String(descriptor.getValue())); 1367 } 1368 } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) { 1369 if (uid.equals(DESCRIPTOR_NO_WRITE_UUID)) { 1370 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), 1371 BleServerService.DESCRIPTOR_WRITE_NO_PERMISSION); 1372 notifyDescriptorWriteNoPermission(); 1373 } else { 1374 notifyError("Not Permission Write: " + status + " : " + descriptor.getUuid()); 1375 } 1376 } else { 1377 notifyError("Failed to write descriptor"); 1378 } 1379 } 1380 1381 @Override 1382 public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, 1383 int status) { 1384 super.onDescriptorRead(gatt, descriptor, status); 1385 // Note: Both this method and onDescriptorRead(byte[]) will be called. 1386 if (DEBUG) { 1387 Log.d(TAG, "onDescriptorRead (deprecated)"); 1388 } 1389 } 1390 1391 @Override 1392 public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, 1393 int status, byte[] value) { 1394 super.onDescriptorRead(gatt, descriptor, status, value); 1395 if (DEBUG) { 1396 Log.d(TAG, "onDescriptorRead (memory safe version)"); 1397 } 1398 1399 UUID uid = descriptor.getUuid(); 1400 String stringValue = new String(value); 1401 if ((status == BluetoothGatt.GATT_SUCCESS)) { 1402 if ((uid != null) && (uid.equals(DESCRIPTOR_UUID))) { 1403 // verify 1404 if (BleServerService.WRITE_VALUE.equals(stringValue)) { 1405 notifyDescriptorRead(stringValue); 1406 } else { 1407 notifyError("Read data is not correct"); 1408 } 1409 } else if (uid.equals(DESCRIPTOR_NEED_ENCRYPTED_READ_UUID)) { 1410 notifyDescriptorReadNeedEncrypted(stringValue); 1411 } 1412 } else if (status == BluetoothGatt.GATT_READ_NOT_PERMITTED) { 1413 if (uid.equals(DESCRIPTOR_NO_READ_UUID)) { 1414 writeCharacteristic(getCharacteristic(CHARACTERISTIC_RESULT_UUID), 1415 BleServerService.DESCRIPTOR_READ_NO_PERMISSION); 1416 notifyDescriptorReadNoPermission(); 1417 } else { 1418 notifyError("Not Permission Read: " + status + " : " + descriptor.getUuid()); 1419 } 1420 } else { 1421 notifyError("Failed to read descriptor: " + status); 1422 } 1423 } 1424 1425 @Override 1426 public void onCharacteristicChanged(BluetoothGatt gatt, 1427 BluetoothGattCharacteristic characteristic) { 1428 super.onCharacteristicChanged(gatt, characteristic); 1429 UUID uid = characteristic.getUuid(); 1430 // Note: Both this method and onCharacteristicChanged(byte[]) will be called. 1431 if (DEBUG) { 1432 Log.d(TAG, "onCharacteristicChanged (deprecated): uid=" + uid); 1433 } 1434 } 1435 1436 @Override 1437 public void onCharacteristicChanged(BluetoothGatt gatt, 1438 BluetoothGattCharacteristic characteristic, byte[] value) { 1439 super.onCharacteristicChanged(gatt, characteristic, value); 1440 UUID uid = characteristic.getUuid(); 1441 if (DEBUG) { 1442 Log.d(TAG, "onCharacteristicChanged (memory safe version): uid=" + uid); 1443 } 1444 1445 String stringValue = new String(value); 1446 if (uid != null) { 1447 if (uid.equals(INDICATE_CHARACTERISTIC_UUID) 1448 && BleServerService.INDICATE_VALUE.equals(stringValue)) { 1449 setNotification(characteristic, false); 1450 notifyCharacteristicIndicated(); 1451 } else if (BleServerService.NOTIFY_VALUE.equals(stringValue)) { 1452 mNotifyCount--; 1453 setNotification(characteristic, false); 1454 if (mNotifyCount == 0) { 1455 notifyCharacteristicChanged(); 1456 } 1457 } 1458 } 1459 } 1460 1461 @Override 1462 public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { 1463 super.onReliableWriteCompleted(gatt, status); 1464 if (DEBUG) { 1465 Log.d(TAG, "onReliableWriteComplete: " + status); 1466 } 1467 1468 if (mExecReliableWrite != ReliableWriteState.RELIABLE_WRITE_NONE) { 1469 if (status == BluetoothGatt.GATT_SUCCESS) { 1470 notifyReliableWriteCompleted(); 1471 } else { 1472 notifyError("Failed to complete reliable write: " + status); 1473 } 1474 mExecReliableWrite = ReliableWriteState.RELIABLE_WRITE_NONE; 1475 } 1476 } 1477 1478 @Override 1479 public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { 1480 super.onReadRemoteRssi(gatt, rssi, status); 1481 if (DEBUG) { 1482 Log.d(TAG, "onReadRemoteRssi"); 1483 } 1484 if (status == BluetoothGatt.GATT_SUCCESS) { 1485 notifyReadRemoteRssi(rssi); 1486 } else { 1487 notifyError("Failed to read remote rssi"); 1488 } 1489 } 1490 1491 @Override 1492 public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) { 1493 super.onPhyRead(gatt, txPhy, rxPhy, status); 1494 if (DEBUG) { 1495 Log.d(TAG, "onPhyRead status=" + status); 1496 } 1497 if (status == BluetoothGatt.GATT_SUCCESS) { 1498 notifyPhyRead(txPhy, rxPhy); 1499 } else if (status == BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED) { 1500 notifyPhyReadSkipped(); 1501 } else { 1502 notifyError("Failed to read phy"); 1503 } 1504 } 1505 1506 @Override 1507 public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) { 1508 super.onPhyUpdate(gatt, txPhy, rxPhy, status); 1509 if (DEBUG) { 1510 Log.d(TAG, "onPhyUpdate status=" + status); 1511 } 1512 if (status == BluetoothGatt.GATT_SUCCESS) { 1513 notifyPhyUpdate(txPhy, rxPhy); 1514 } else if (status == BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED) { 1515 notifyPhyUpdateSkipped(); 1516 } else { 1517 notifyError("Failed to update phy"); 1518 } 1519 } 1520 1521 @Override 1522 public void onServiceChanged(BluetoothGatt gatt) { 1523 super.onServiceChanged(gatt); 1524 if (DEBUG) { 1525 Log.d(TAG, "onServiceChanged"); 1526 } 1527 1528 if (BLE_CLIENT_ACTION_TRIGGER_SERVICE_CHANGED.equals(mCurrentAction)) { 1529 sendServiceChangedEventIfReady(SERVICE_CHANGED_FLAG_ON_SERVICE_CHANGED); 1530 } 1531 } 1532 }; 1533 1534 private final ScanCallback mScanCallback = new ScanCallback() { 1535 @Override 1536 public void onScanResult(int callbackType, ScanResult result) { 1537 if (mBluetoothGatt == null) { 1538 // verify the validity of the advertisement packet. 1539 mValidityService = false; 1540 List<ParcelUuid> uuids = result.getScanRecord().getServiceUuids(); 1541 for (ParcelUuid uuid : uuids) { 1542 if (uuid.getUuid().equals(BleServerService.ADV_SERVICE_UUID)) { 1543 mValidityService = true; 1544 break; 1545 } 1546 } 1547 if (mValidityService) { 1548 stopScan(); 1549 1550 BluetoothDevice device = result.getDevice(); 1551 if (mSecure) { 1552 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { 1553 if (!device.createBond()) { 1554 notifyError("Failed to call create bond"); 1555 } 1556 } else { 1557 mBluetoothGatt = connectGatt(result.getDevice(), mContext, false, 1558 mSecure, mGattCallbacks); 1559 } 1560 } else { 1561 mBluetoothGatt = connectGatt(result.getDevice(), mContext, false, mSecure, 1562 mGattCallbacks); 1563 } 1564 } else { 1565 notifyError("There is no validity to Advertise servie."); 1566 } 1567 } 1568 } 1569 }; 1570 startScan()1571 private void startScan() { 1572 if (DEBUG) Log.d(TAG, "startScan"); 1573 List<ScanFilter> filter = Arrays.asList(new ScanFilter.Builder().setServiceUuid( 1574 new ParcelUuid(BleServerService.ADV_SERVICE_UUID)).build()); 1575 ScanSettings setting = new ScanSettings.Builder() 1576 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 1577 mScanner.startScan(filter, setting, mScanCallback); 1578 } 1579 stopScan()1580 private void stopScan() { 1581 if (DEBUG) Log.d(TAG, "stopScan"); 1582 if (mScanner != null) { 1583 mScanner.stopScan(mScanCallback); 1584 } 1585 } 1586 createTestData(String prefix, int length)1587 private static String createTestData(String prefix, int length) { 1588 StringBuilder builder = new StringBuilder(); 1589 builder.append(prefix); 1590 int len = length - builder.length(); 1591 for (int i = 0; i < len; ++i) { 1592 builder.append("" + (i % 10)); 1593 } 1594 return builder.toString(); 1595 } 1596 1597 private final BroadcastReceiver mBondStatusReceiver = new BroadcastReceiver() { 1598 @Override 1599 public void onReceive(Context context, Intent intent) { 1600 if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) { 1601 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 1602 int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 1603 BluetoothDevice.BOND_NONE); 1604 switch (state) { 1605 case BluetoothDevice.BOND_BONDED: 1606 if ((mBluetoothGatt == null) && 1607 (device.getType() != BluetoothDevice.DEVICE_TYPE_CLASSIC)) { 1608 if (DEBUG) { 1609 Log.d(TAG, "onReceive:BOND_BONDED: calling connectGatt device=" 1610 + device + ", mSecure=" + mSecure); 1611 } 1612 mBluetoothGatt = connectGatt(device, mContext, false, mSecure, 1613 mGattCallbacks); 1614 } 1615 break; 1616 case BluetoothDevice.BOND_NONE: 1617 notifyError("Failed to create bond."); 1618 break; 1619 case BluetoothDevice.BOND_BONDING: 1620 default: // fall through 1621 // wait for next state 1622 break; 1623 } 1624 } 1625 } 1626 }; 1627 } 1628