1 /* 2 * Copyright (C) 2014 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 android.bluetooth.le; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SuppressLint; 23 import android.annotation.SystemApi; 24 import android.bluetooth.BluetoothUuid; 25 import android.compat.annotation.UnsupportedAppUsage; 26 import android.os.ParcelUuid; 27 import android.util.ArrayMap; 28 import android.util.Log; 29 import android.util.SparseArray; 30 31 import java.lang.annotation.Retention; 32 import java.lang.annotation.RetentionPolicy; 33 import java.util.ArrayList; 34 import java.util.Arrays; 35 import java.util.HashMap; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.function.Predicate; 39 40 /** 41 * Represents a scan record from Bluetooth LE scan. 42 */ 43 @SuppressLint("AndroidFrameworkBluetoothPermission") 44 public final class ScanRecord { 45 46 private static final String TAG = "ScanRecord"; 47 48 /** @hide */ 49 @IntDef(prefix = "DATA_TYPE_", value = { 50 DATA_TYPE_FLAGS, 51 DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL, 52 DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE, 53 DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL, 54 DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE, 55 DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL, 56 DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE, 57 DATA_TYPE_LOCAL_NAME_SHORT, 58 DATA_TYPE_LOCAL_NAME_COMPLETE, 59 DATA_TYPE_TX_POWER_LEVEL, 60 DATA_TYPE_CLASS_OF_DEVICE, 61 DATA_TYPE_SIMPLE_PAIRING_HASH_C, 62 DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R, 63 DATA_TYPE_DEVICE_ID, 64 DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS, 65 DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE, 66 DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT, 67 DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT, 68 DATA_TYPE_SERVICE_DATA_16_BIT, 69 DATA_TYPE_PUBLIC_TARGET_ADDRESS, 70 DATA_TYPE_RANDOM_TARGET_ADDRESS, 71 DATA_TYPE_APPEARANCE, 72 DATA_TYPE_ADVERTISING_INTERVAL, 73 DATA_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS, 74 DATA_TYPE_LE_ROLE, 75 DATA_TYPE_SIMPLE_PAIRING_HASH_C_256, 76 DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_256, 77 DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT, 78 DATA_TYPE_SERVICE_DATA_32_BIT, 79 DATA_TYPE_SERVICE_DATA_128_BIT, 80 DATA_TYPE_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE, 81 DATA_TYPE_LE_SECURE_CONNECTIONS_RANDOM_VALUE, 82 DATA_TYPE_URI, 83 DATA_TYPE_INDOOR_POSITIONING, 84 DATA_TYPE_TRANSPORT_DISCOVERY_DATA, 85 DATA_TYPE_LE_SUPPORTED_FEATURES, 86 DATA_TYPE_CHANNEL_MAP_UPDATE_INDICATION, 87 DATA_TYPE_PB_ADV, 88 DATA_TYPE_MESH_MESSAGE, 89 DATA_TYPE_MESH_BEACON, 90 DATA_TYPE_BIG_INFO, 91 DATA_TYPE_BROADCAST_CODE, 92 DATA_TYPE_RESOLVABLE_SET_IDENTIFIER, 93 DATA_TYPE_ADVERTISING_INTERVAL_LONG, 94 DATA_TYPE_3D_INFORMATION_DATA, 95 DATA_TYPE_MANUFACTURER_SPECIFIC_DATA, 96 }) 97 @Retention(RetentionPolicy.SOURCE) 98 public @interface AdvertisingDataType {} 99 100 /** 101 * Data type is not set for the filter. Will not filter advertising data type. 102 */ 103 public static final int DATA_TYPE_NONE = -1; 104 /** 105 * Data type is Flags, see the Bluetooth Generic Access Profile for more details. 106 */ 107 public static final int DATA_TYPE_FLAGS = 0x01; 108 /** 109 * Data type is Incomplete List of 16-bit Service Class UUIDs, see the Bluetooth Generic Access 110 * Profile for the details. 111 */ 112 public static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL = 0x02; 113 /** 114 * Data type is Complete List of 16-bit Service Class UUIDs, see the Bluetooth Generic Access 115 * Profile for more details. 116 */ 117 public static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE = 0x03; 118 /** 119 * Data type is Incomplete List of 32-bit Service Class UUIDs, see the Bluetooth Generic Access 120 * Profile for the details. 121 */ 122 public static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL = 0x04; 123 /** 124 * Data type is Complete List of 32-bit Service Class UUIDs, see the Bluetooth Generic Access 125 * Profile for more details. 126 */ 127 public static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE = 0x05; 128 /** 129 * Data type is Incomplete List of 128-bit Service Class UUIDs, see the Bluetooth Generic Access 130 * Profile for the details. 131 */ 132 public static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL = 0x06; 133 /** 134 * Data type is Complete List of 128-bit Service Class UUIDs, see the Bluetooth Generic Access 135 * Profile for more details. 136 */ 137 public static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE = 0x07; 138 /** 139 * Data type is Shortened Local Name, see the Bluetooth Generic Access Profile for more details. 140 */ 141 public static final int DATA_TYPE_LOCAL_NAME_SHORT = 0x08; 142 /** 143 * Data type is Complete Local Name, see the Bluetooth Generic Access Profile for more details. 144 */ 145 public static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09; 146 /** 147 * Data type is Tx Power Level, see the Bluetooth Generic Access Profile for more details. 148 */ 149 public static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A; 150 /** 151 * Data type is Class of Device, see the Bluetooth Generic Access Profile for more details. 152 */ 153 public static final int DATA_TYPE_CLASS_OF_DEVICE = 0x0D; 154 /** 155 * Data type is Simple Pairing Hash C, see the Bluetooth Generic Access Profile for more 156 * details. 157 */ 158 public static final int DATA_TYPE_SIMPLE_PAIRING_HASH_C = 0x0E; 159 /** 160 * Data type is Simple Pairing Randomizer R, see the Bluetooth Generic Access Profile for more 161 * details. 162 */ 163 public static final int DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R = 0x0F; 164 /** 165 * Data type is Device ID, see the Bluetooth Generic Access Profile for more details. 166 */ 167 public static final int DATA_TYPE_DEVICE_ID = 0x10; 168 /** 169 * Data type is Security Manager Out of Band Flags, see the Bluetooth Generic Access Profile for 170 * more details. 171 */ 172 public static final int DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS = 0x11; 173 /** 174 * Data type is Slave Connection Interval Range, see the Bluetooth Generic Access Profile for 175 * more details. 176 */ 177 public static final int DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE = 0x12; 178 /** 179 * Data type is List of 16-bit Service Solicitation UUIDs, see the Bluetooth Generic Access 180 * Profile for more details. 181 */ 182 public static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT = 0x14; 183 /** 184 * Data type is List of 128-bit Service Solicitation UUIDs, see the Bluetooth Generic Access 185 * Profile for more details. 186 */ 187 public static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT = 0x15; 188 /** 189 * Data type is Service Data - 16-bit UUID, see the Bluetooth Generic Access Profile for more 190 * details. 191 */ 192 public static final int DATA_TYPE_SERVICE_DATA_16_BIT = 0x16; 193 /** 194 * Data type is Public Target Address, see the Bluetooth Generic Access Profile for more 195 * details. 196 */ 197 public static final int DATA_TYPE_PUBLIC_TARGET_ADDRESS = 0x17; 198 /** 199 * Data type is Random Target Address, see the Bluetooth Generic Access Profile for more 200 * details. 201 */ 202 public static final int DATA_TYPE_RANDOM_TARGET_ADDRESS = 0x18; 203 /** 204 * Data type is Appearance, see the Bluetooth Generic Access Profile for more details. 205 */ 206 public static final int DATA_TYPE_APPEARANCE = 0x19; 207 /** 208 * Data type is Advertising Interval, see the Bluetooth Generic Access Profile for more details. 209 */ 210 public static final int DATA_TYPE_ADVERTISING_INTERVAL = 0x1A; 211 /** 212 * Data type is LE Bluetooth Device Address, see the Bluetooth Generic Access Profile for more 213 * details. 214 */ 215 public static final int DATA_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS = 0x1B; 216 /** 217 * Data type is LE Role, see the Bluetooth Generic Access Profile for more details. 218 */ 219 public static final int DATA_TYPE_LE_ROLE = 0x1C; 220 /** 221 * Data type is Simple Pairing Hash C-256, see the Bluetooth Generic Access Profile for more 222 * details. 223 */ 224 public static final int DATA_TYPE_SIMPLE_PAIRING_HASH_C_256 = 0x1D; 225 /** 226 * Data type is Simple Pairing Randomizer R-256, see the Bluetooth Generic Access Profile for 227 * more details. 228 */ 229 public static final int DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_256 = 0x1E; 230 /** 231 * Data type is List of 32-bit Service Solicitation UUIDs, see the Bluetooth Generic Access 232 * Profile for more details. 233 */ 234 public static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT = 0x1F; 235 /** 236 * Data type is Service Data - 32-bit UUID, see the Bluetooth Generic Access Profile for more 237 * details. 238 */ 239 public static final int DATA_TYPE_SERVICE_DATA_32_BIT = 0x20; 240 /** 241 * Data type is Service Data - 128-bit UUID, see the Bluetooth Generic Access Profile for more 242 * details. 243 */ 244 public static final int DATA_TYPE_SERVICE_DATA_128_BIT = 0x21; 245 /** 246 * Data type is LE Secure Connections Confirmation Value, see the Bluetooth Generic Access 247 * Profile for more details. 248 */ 249 public static final int DATA_TYPE_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE = 0x22; 250 /** 251 * Data type is LE Secure Connections Random Value, see the Bluetooth Generic Access Profile for 252 * more details. 253 */ 254 public static final int DATA_TYPE_LE_SECURE_CONNECTIONS_RANDOM_VALUE = 0x23; 255 /** 256 * Data type is URI, see the Bluetooth Generic Access Profile for more details. 257 */ 258 public static final int DATA_TYPE_URI = 0x24; 259 /** 260 * Data type is Indoor Positioning, see the Bluetooth Generic Access Profile for more details. 261 */ 262 public static final int DATA_TYPE_INDOOR_POSITIONING = 0x25; 263 /** 264 * Data type is Transport Discovery Data, see the Bluetooth Generic Access Profile for more 265 * details. 266 */ 267 public static final int DATA_TYPE_TRANSPORT_DISCOVERY_DATA = 0x26; 268 /** 269 * Data type is LE Supported Features, see the Bluetooth Generic Access Profile for more 270 * details. 271 */ 272 public static final int DATA_TYPE_LE_SUPPORTED_FEATURES = 0x27; 273 /** 274 * Data type is Channel Map Update Indication, see the Bluetooth Generic Access Profile for more 275 * details. 276 */ 277 public static final int DATA_TYPE_CHANNEL_MAP_UPDATE_INDICATION = 0x28; 278 /** 279 * Data type is PB-ADV, see the Bluetooth Generic Access Profile for more details. 280 */ 281 public static final int DATA_TYPE_PB_ADV = 0x29; 282 /** 283 * Data type is Mesh Message, see the Bluetooth Generic Access Profile for more details. 284 */ 285 public static final int DATA_TYPE_MESH_MESSAGE = 0x2A; 286 /** 287 * Data type is Mesh Beacon, see the Bluetooth Generic Access Profile for more details. 288 */ 289 public static final int DATA_TYPE_MESH_BEACON = 0x2B; 290 /** 291 * Data type is BIGInfo, see the Bluetooth Generic Access Profile for more details. 292 */ 293 public static final int DATA_TYPE_BIG_INFO = 0x2C; 294 /** 295 * Data type is Broadcast_Code, see the Bluetooth Generic Access Profile for more details. 296 */ 297 public static final int DATA_TYPE_BROADCAST_CODE = 0x2D; 298 /** 299 * Data type is Resolvable Set Identifier, see the Bluetooth Generic Access Profile for more 300 * details. 301 */ 302 public static final int DATA_TYPE_RESOLVABLE_SET_IDENTIFIER = 0x2E; 303 /** 304 * Data type is Advertising Interval - long, see the Bluetooth Generic Access Profile for more 305 * details. 306 */ 307 public static final int DATA_TYPE_ADVERTISING_INTERVAL_LONG = 0x2F; 308 /** 309 * Data type is 3D Information Data, see the Bluetooth Generic Access Profile for more details. 310 */ 311 public static final int DATA_TYPE_3D_INFORMATION_DATA = 0x3D; 312 /** 313 * Data type is Manufacturer Specific Data, see the Bluetooth Generic Access Profile for more 314 * details. 315 */ 316 public static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF; 317 318 // Flags of the advertising data. 319 private final int mAdvertiseFlags; 320 321 @Nullable 322 private final List<ParcelUuid> mServiceUuids; 323 @Nullable 324 private final List<ParcelUuid> mServiceSolicitationUuids; 325 326 private final SparseArray<byte[]> mManufacturerSpecificData; 327 328 private final Map<ParcelUuid, byte[]> mServiceData; 329 330 // Transmission power level(in dB). 331 private final int mTxPowerLevel; 332 333 // Local name of the Bluetooth LE device. 334 private final String mDeviceName; 335 336 // Raw bytes of scan record. 337 private final byte[] mBytes; 338 339 private final HashMap<Integer, byte[]> mAdvertisingDataMap; 340 341 // Transport Discovery data. 342 private final TransportDiscoveryData mTransportDiscoveryData; 343 344 /** 345 * Returns the advertising flags indicating the discoverable mode and capability of the device. 346 * Returns -1 if the flag field is not set. 347 */ getAdvertiseFlags()348 public int getAdvertiseFlags() { 349 return mAdvertiseFlags; 350 } 351 352 /** 353 * Returns a list of service UUIDs within the advertisement that are used to identify the 354 * bluetooth GATT services. 355 */ getServiceUuids()356 public List<ParcelUuid> getServiceUuids() { 357 return mServiceUuids; 358 } 359 360 /** 361 * Returns a list of service solicitation UUIDs within the advertisement that are used to 362 * identify the Bluetooth GATT services. 363 */ 364 @NonNull getServiceSolicitationUuids()365 public List<ParcelUuid> getServiceSolicitationUuids() { 366 return mServiceSolicitationUuids; 367 } 368 369 /** 370 * Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific 371 * data. 372 */ getManufacturerSpecificData()373 public SparseArray<byte[]> getManufacturerSpecificData() { 374 return mManufacturerSpecificData; 375 } 376 377 /** 378 * Returns the manufacturer specific data associated with the manufacturer id. Returns 379 * {@code null} if the {@code manufacturerId} is not found. 380 */ 381 @Nullable getManufacturerSpecificData(int manufacturerId)382 public byte[] getManufacturerSpecificData(int manufacturerId) { 383 if (mManufacturerSpecificData == null) { 384 return null; 385 } 386 return mManufacturerSpecificData.get(manufacturerId); 387 } 388 389 /** 390 * Returns a map of service UUID and its corresponding service data. 391 */ getServiceData()392 public Map<ParcelUuid, byte[]> getServiceData() { 393 return mServiceData; 394 } 395 396 /** 397 * Returns the service data byte array associated with the {@code serviceUuid}. Returns 398 * {@code null} if the {@code serviceDataUuid} is not found. 399 */ 400 @Nullable getServiceData(ParcelUuid serviceDataUuid)401 public byte[] getServiceData(ParcelUuid serviceDataUuid) { 402 if (serviceDataUuid == null || mServiceData == null) { 403 return null; 404 } 405 return mServiceData.get(serviceDataUuid); 406 } 407 408 /** 409 * Returns the transmission power level of the packet in dBm. Returns {@link Integer#MIN_VALUE} 410 * if the field is not set. This value can be used to calculate the path loss of a received 411 * packet using the following equation: 412 * <p> 413 * <code>pathloss = txPowerLevel - rssi</code> 414 */ getTxPowerLevel()415 public int getTxPowerLevel() { 416 return mTxPowerLevel; 417 } 418 419 /** 420 * Returns the local name of the BLE device. This is a UTF-8 encoded string. 421 */ 422 @Nullable getDeviceName()423 public String getDeviceName() { 424 return mDeviceName; 425 } 426 427 428 /** 429 * Returns a map of advertising data type and its corresponding advertising data. 430 * The values of advertising data type are defined in the Bluetooth Generic Access Profile 431 * (https://www.bluetooth.com/specifications/assigned-numbers/) 432 */ getAdvertisingDataMap()433 public @NonNull Map<Integer, byte[]> getAdvertisingDataMap() { 434 return mAdvertisingDataMap; 435 } 436 437 /** 438 * Returns Transport Discovery data, {@code null} if Transport Discovery data is not found. 439 * 440 * @hide 441 */ 442 @SystemApi 443 @Nullable getTransportDiscoveryData()444 public TransportDiscoveryData getTransportDiscoveryData() { 445 return mTransportDiscoveryData; 446 } 447 448 /** 449 * Returns raw bytes of scan record. 450 */ getBytes()451 public byte[] getBytes() { 452 return mBytes; 453 } 454 455 /** 456 * Test if any fields contained inside this scan record are matched by the 457 * given matcher. 458 * 459 * @hide 460 */ matchesAnyField(@onNull Predicate<byte[]> matcher)461 public boolean matchesAnyField(@NonNull Predicate<byte[]> matcher) { 462 int pos = 0; 463 while (pos < mBytes.length) { 464 final int length = mBytes[pos] & 0xFF; 465 if (length == 0) { 466 break; 467 } 468 if (matcher.test(Arrays.copyOfRange(mBytes, pos, pos + length + 1))) { 469 return true; 470 } 471 pos += length + 1; 472 } 473 return false; 474 } 475 ScanRecord(List<ParcelUuid> serviceUuids, List<ParcelUuid> serviceSolicitationUuids, SparseArray<byte[]> manufacturerData, Map<ParcelUuid, byte[]> serviceData, int advertiseFlags, int txPowerLevel, String localName, HashMap<Integer, byte[]> advertisingDataMap, TransportDiscoveryData transportDiscoveryData, byte[] bytes)476 private ScanRecord(List<ParcelUuid> serviceUuids, 477 List<ParcelUuid> serviceSolicitationUuids, 478 SparseArray<byte[]> manufacturerData, 479 Map<ParcelUuid, byte[]> serviceData, 480 int advertiseFlags, int txPowerLevel, 481 String localName, HashMap<Integer, byte[]> advertisingDataMap, 482 TransportDiscoveryData transportDiscoveryData, byte[] bytes) { 483 mServiceSolicitationUuids = serviceSolicitationUuids; 484 mServiceUuids = serviceUuids; 485 mManufacturerSpecificData = manufacturerData; 486 mServiceData = serviceData; 487 mDeviceName = localName; 488 mAdvertiseFlags = advertiseFlags; 489 mTxPowerLevel = txPowerLevel; 490 mAdvertisingDataMap = advertisingDataMap; 491 mTransportDiscoveryData = transportDiscoveryData; 492 mBytes = bytes; 493 } 494 495 /** 496 * Parse scan record bytes to {@link ScanRecord}. 497 * <p> 498 * The format is defined in Bluetooth 4.1 specification, Volume 3, Part C, Section 11 and 18. 499 * <p> 500 * All numerical multi-byte entities and values shall use little-endian <strong>byte</strong> 501 * order. 502 * 503 * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response. 504 * @hide 505 */ 506 @UnsupportedAppUsage parseFromBytes(byte[] scanRecord)507 public static ScanRecord parseFromBytes(byte[] scanRecord) { 508 if (scanRecord == null) { 509 return null; 510 } 511 512 int currentPos = 0; 513 int advertiseFlag = -1; 514 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 515 List<ParcelUuid> serviceSolicitationUuids = new ArrayList<ParcelUuid>(); 516 String localName = null; 517 int txPowerLevel = Integer.MIN_VALUE; 518 519 SparseArray<byte[]> manufacturerData = new SparseArray<byte[]>(); 520 Map<ParcelUuid, byte[]> serviceData = new ArrayMap<ParcelUuid, byte[]>(); 521 HashMap<Integer, byte[]> advertisingDataMap = new HashMap<Integer, byte[]>(); 522 523 TransportDiscoveryData transportDiscoveryData = null; 524 525 try { 526 while (currentPos < scanRecord.length) { 527 // length is unsigned int. 528 int length = scanRecord[currentPos++] & 0xFF; 529 if (length == 0) { 530 break; 531 } 532 // Note the length includes the length of the field type itself. 533 int dataLength = length - 1; 534 // fieldType is unsigned int. 535 int fieldType = scanRecord[currentPos++] & 0xFF; 536 byte[] advertisingData = extractBytes(scanRecord, currentPos, dataLength); 537 advertisingDataMap.put(fieldType, advertisingData); 538 switch (fieldType) { 539 case DATA_TYPE_FLAGS: 540 advertiseFlag = scanRecord[currentPos] & 0xFF; 541 break; 542 case DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL: 543 case DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE: 544 parseServiceUuid(scanRecord, currentPos, 545 dataLength, BluetoothUuid.UUID_BYTES_16_BIT, serviceUuids); 546 break; 547 case DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL: 548 case DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE: 549 parseServiceUuid(scanRecord, currentPos, dataLength, 550 BluetoothUuid.UUID_BYTES_32_BIT, serviceUuids); 551 break; 552 case DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL: 553 case DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE: 554 parseServiceUuid(scanRecord, currentPos, dataLength, 555 BluetoothUuid.UUID_BYTES_128_BIT, serviceUuids); 556 break; 557 case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT: 558 parseServiceSolicitationUuid(scanRecord, currentPos, dataLength, 559 BluetoothUuid.UUID_BYTES_16_BIT, serviceSolicitationUuids); 560 break; 561 case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT: 562 parseServiceSolicitationUuid(scanRecord, currentPos, dataLength, 563 BluetoothUuid.UUID_BYTES_32_BIT, serviceSolicitationUuids); 564 break; 565 case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT: 566 parseServiceSolicitationUuid(scanRecord, currentPos, dataLength, 567 BluetoothUuid.UUID_BYTES_128_BIT, serviceSolicitationUuids); 568 break; 569 case DATA_TYPE_LOCAL_NAME_SHORT: 570 case DATA_TYPE_LOCAL_NAME_COMPLETE: 571 localName = new String( 572 extractBytes(scanRecord, currentPos, dataLength)); 573 break; 574 case DATA_TYPE_TX_POWER_LEVEL: 575 txPowerLevel = scanRecord[currentPos]; 576 break; 577 case DATA_TYPE_SERVICE_DATA_16_BIT: 578 case DATA_TYPE_SERVICE_DATA_32_BIT: 579 case DATA_TYPE_SERVICE_DATA_128_BIT: 580 int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT; 581 if (fieldType == DATA_TYPE_SERVICE_DATA_32_BIT) { 582 serviceUuidLength = BluetoothUuid.UUID_BYTES_32_BIT; 583 } else if (fieldType == DATA_TYPE_SERVICE_DATA_128_BIT) { 584 serviceUuidLength = BluetoothUuid.UUID_BYTES_128_BIT; 585 } 586 587 byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos, 588 serviceUuidLength); 589 ParcelUuid serviceDataUuid = BluetoothUuid.parseUuidFrom( 590 serviceDataUuidBytes); 591 byte[] serviceDataArray = extractBytes(scanRecord, 592 currentPos + serviceUuidLength, dataLength - serviceUuidLength); 593 serviceData.put(serviceDataUuid, serviceDataArray); 594 break; 595 case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: 596 // The first two bytes of the manufacturer specific data are 597 // manufacturer ids in little endian. 598 int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) 599 + (scanRecord[currentPos] & 0xFF); 600 byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2, 601 dataLength - 2); 602 manufacturerData.put(manufacturerId, manufacturerDataBytes); 603 break; 604 case DATA_TYPE_TRANSPORT_DISCOVERY_DATA: 605 // -1 / +1 to include the type in the extract 606 byte[] transportDiscoveryDataBytes = 607 extractBytes(scanRecord, currentPos - 1, dataLength + 1); 608 transportDiscoveryData = 609 new TransportDiscoveryData(transportDiscoveryDataBytes); 610 break; 611 612 default: 613 // Just ignore, we don't handle such data type. 614 break; 615 } 616 currentPos += dataLength; 617 } 618 619 if (serviceUuids.isEmpty()) { 620 serviceUuids = null; 621 } 622 return new ScanRecord(serviceUuids, serviceSolicitationUuids, manufacturerData, 623 serviceData, advertiseFlag, txPowerLevel, localName, advertisingDataMap, 624 transportDiscoveryData, scanRecord); 625 } catch (Exception e) { 626 Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord)); 627 // As the record is invalid, ignore all the parsed results for this packet 628 // and return an empty record with raw scanRecord bytes in results 629 return new ScanRecord(null, null, null, null, -1, Integer.MIN_VALUE, null, 630 advertisingDataMap, null, scanRecord); 631 } 632 } 633 634 @Override toString()635 public String toString() { 636 return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids 637 + ", mServiceSolicitationUuids=" + mServiceSolicitationUuids 638 + ", mManufacturerSpecificData=" 639 + BluetoothLeUtils.toString(mManufacturerSpecificData) 640 + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) 641 + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName 642 + ", mTransportDiscoveryData=" + mTransportDiscoveryData + "]"; 643 } 644 645 // Parse service UUIDs. parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength, int uuidLength, List<ParcelUuid> serviceUuids)646 private static int parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength, 647 int uuidLength, List<ParcelUuid> serviceUuids) { 648 while (dataLength > 0) { 649 byte[] uuidBytes = extractBytes(scanRecord, currentPos, 650 uuidLength); 651 serviceUuids.add(BluetoothUuid.parseUuidFrom(uuidBytes)); 652 dataLength -= uuidLength; 653 currentPos += uuidLength; 654 } 655 return currentPos; 656 } 657 658 /** 659 * Parse service Solicitation UUIDs. 660 */ parseServiceSolicitationUuid(byte[] scanRecord, int currentPos, int dataLength, int uuidLength, List<ParcelUuid> serviceSolicitationUuids)661 private static int parseServiceSolicitationUuid(byte[] scanRecord, int currentPos, 662 int dataLength, int uuidLength, List<ParcelUuid> serviceSolicitationUuids) { 663 while (dataLength > 0) { 664 byte[] uuidBytes = extractBytes(scanRecord, currentPos, uuidLength); 665 serviceSolicitationUuids.add(BluetoothUuid.parseUuidFrom(uuidBytes)); 666 dataLength -= uuidLength; 667 currentPos += uuidLength; 668 } 669 return currentPos; 670 } 671 672 // Helper method to extract bytes from byte array. extractBytes(byte[] scanRecord, int start, int length)673 private static byte[] extractBytes(byte[] scanRecord, int start, int length) { 674 byte[] bytes = new byte[length]; 675 System.arraycopy(scanRecord, start, bytes, 0, length); 676 return bytes; 677 } 678 } 679