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