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