ScanRecord.java revision 685c1758902a42a7beb030d8bbaed3f7ce6f6135
16d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang/* 26d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Copyright (C) 2014 The Android Open Source Project 36d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 46d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Licensed under the Apache License, Version 2.0 (the "License"); 56d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * you may not use this file except in compliance with the License. 66d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * You may obtain a copy of the License at 76d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 86d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * http://www.apache.org/licenses/LICENSE-2.0 96d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 106d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Unless required by applicable law or agreed to in writing, software 116d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * distributed under the License is distributed on an "AS IS" BASIS, 126d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * See the License for the specific language governing permissions and 146d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * limitations under the License. 156d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 166d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 176d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangpackage android.bluetooth.le; 186d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 196d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.annotation.Nullable; 206d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.bluetooth.BluetoothUuid; 216d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.os.ParcelUuid; 226d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.util.Log; 236d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 246d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport java.util.ArrayList; 256d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport java.util.Arrays; 266d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport java.util.List; 276d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 286d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang/** 296d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Represents a scan record from Bluetooth LE scan. 306d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 316d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangpublic final class ScanRecord { 326d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 336d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final String TAG = "ScanRecord"; 346d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 356d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // The following data type values are assigned by Bluetooth SIG. 366d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // For more details refer to Bluetooth 4.1 specification, Volume 3, Part C, Section 18. 376d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_FLAGS = 0x01; 386d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL = 0x02; 396d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE = 0x03; 406d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL = 0x04; 416d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE = 0x05; 426d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL = 0x06; 436d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE = 0x07; 446d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_LOCAL_NAME_SHORT = 0x08; 456d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09; 466d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A; 476d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_SERVICE_DATA = 0x16; 486d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF; 496d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 506d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // Flags of the advertising data. 516d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final int mAdvertiseFlags; 526d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 536d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang @Nullable 546d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final List<ParcelUuid> mServiceUuids; 556d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 566d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final int mManufacturerId; 576d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang @Nullable 586d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final byte[] mManufacturerSpecificData; 596d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 606d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang @Nullable 616d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final ParcelUuid mServiceDataUuid; 626d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang @Nullable 636d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final byte[] mServiceData; 646d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 656d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // Transmission power level(in dB). 666d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final int mTxPowerLevel; 676d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 686d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // Local name of the Bluetooth LE device. 69af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang private final String mDeviceName; 706d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 71685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang // Raw bytes of scan record. 72685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang private final byte[] mBytes; 73685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang 746d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 756d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Returns the advertising flags indicating the discoverable mode and capability of the device. 766d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Returns -1 if the flag field is not set. 776d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 786d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public int getAdvertiseFlags() { 796d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return mAdvertiseFlags; 806d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 816d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 826d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 83af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * Returns a list of service UUIDs within the advertisement that are used to identify the 846d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * bluetooth gatt services. 856d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 866d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public List<ParcelUuid> getServiceUuids() { 876d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return mServiceUuids; 886d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 896d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 906d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 916d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Returns the manufacturer identifier, which is a non-negative number assigned by Bluetooth 926d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * SIG. 936d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 946d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public int getManufacturerId() { 956d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return mManufacturerId; 966d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 976d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 986d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 996d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Returns the manufacturer specific data which is the content of manufacturer specific data 100af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * field. 1016d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 1026d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public byte[] getManufacturerSpecificData() { 1036d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return mManufacturerSpecificData; 1046d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 1056d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 1066d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 107af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * Returns a 16-bit UUID of the service that the service data is associated with. 1086d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 1096d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public ParcelUuid getServiceDataUuid() { 1106d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return mServiceDataUuid; 1116d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 1126d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 1136d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 114af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * Returns service data. 1156d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 1166d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public byte[] getServiceData() { 1176d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return mServiceData; 1186d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 1196d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 1206d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 1216d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Returns the transmission power level of the packet in dBm. Returns {@link Integer#MIN_VALUE} 1226d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * if the field is not set. This value can be used to calculate the path loss of a received 1236d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * packet using the following equation: 1246d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <p> 1256d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <code>pathloss = txPowerLevel - rssi</code> 1266d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 1276d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public int getTxPowerLevel() { 1286d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return mTxPowerLevel; 1296d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 1306d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 1316d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 1326d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Returns the local name of the BLE device. The is a UTF-8 encoded string. 1336d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 1346d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang @Nullable 135af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang public String getDeviceName() { 136af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang return mDeviceName; 1376d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 1386d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 139685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang /** 140685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * Returns raw bytes of scan record. 141685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang */ 142685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang public byte[] getBytes() { 143685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang return mBytes; 144685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang } 145685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang 1466d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private ScanRecord(List<ParcelUuid> serviceUuids, 1476d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang ParcelUuid serviceDataUuid, byte[] serviceData, 1486d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang int manufacturerId, 1496d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang byte[] manufacturerSpecificData, int advertiseFlags, int txPowerLevel, 150685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang String localName, byte[] bytes) { 1516d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mServiceUuids = serviceUuids; 1526d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mManufacturerId = manufacturerId; 1536d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mManufacturerSpecificData = manufacturerSpecificData; 1546d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mServiceDataUuid = serviceDataUuid; 1556d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mServiceData = serviceData; 156af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang mDeviceName = localName; 1576d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mAdvertiseFlags = advertiseFlags; 1586d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mTxPowerLevel = txPowerLevel; 159685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang mBytes = bytes; 1606d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 1616d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 1626d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 1636d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Parse scan record bytes to {@link ScanRecord}. 1646d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <p> 1656d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * The format is defined in Bluetooth 4.1 specification, Volume 3, Part C, Section 11 and 18. 1666d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <p> 1676d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * All numerical multi-byte entities and values shall use little-endian <strong>byte</strong> 1686d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * order. 1696d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 1706d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response. 171685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * 172685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * @hide 1736d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 1746d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public static ScanRecord parseFromBytes(byte[] scanRecord) { 1756d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang if (scanRecord == null) { 1766d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return null; 1776d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 1786d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 1796d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang int currentPos = 0; 1806d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang int advertiseFlag = -1; 1816d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1826d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang String localName = null; 1836d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang int txPowerLevel = Integer.MIN_VALUE; 1846d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang ParcelUuid serviceDataUuid = null; 1856d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang byte[] serviceData = null; 1866d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang int manufacturerId = -1; 1876d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang byte[] manufacturerSpecificData = null; 1886d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 1896d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang try { 1906d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang while (currentPos < scanRecord.length) { 1916d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // length is unsigned int. 1926d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang int length = scanRecord[currentPos++] & 0xFF; 1936d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang if (length == 0) { 1946d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang break; 1956d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 1966d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // Note the length includes the length of the field type itself. 1976d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang int dataLength = length - 1; 1986d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // fieldType is unsigned int. 1996d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang int fieldType = scanRecord[currentPos++] & 0xFF; 2006d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang switch (fieldType) { 2016d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_FLAGS: 2026d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang advertiseFlag = scanRecord[currentPos] & 0xFF; 2036d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang break; 2046d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL: 2056d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE: 2066d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang parseServiceUuid(scanRecord, currentPos, 2076d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang dataLength, BluetoothUuid.UUID_BYTES_16_BIT, serviceUuids); 2086d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang break; 2096d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL: 2106d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE: 2116d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang parseServiceUuid(scanRecord, currentPos, dataLength, 2126d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang BluetoothUuid.UUID_BYTES_32_BIT, serviceUuids); 2136d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang break; 2146d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL: 2156d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE: 2166d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang parseServiceUuid(scanRecord, currentPos, dataLength, 2176d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang BluetoothUuid.UUID_BYTES_128_BIT, serviceUuids); 2186d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang break; 2196d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_LOCAL_NAME_SHORT: 2206d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_LOCAL_NAME_COMPLETE: 2216d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang localName = new String( 2226d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang extractBytes(scanRecord, currentPos, dataLength)); 2236d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang break; 2246d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_TX_POWER_LEVEL: 2256d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang txPowerLevel = scanRecord[currentPos]; 2266d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang break; 2276d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_SERVICE_DATA: 2286d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang serviceData = extractBytes(scanRecord, currentPos, dataLength); 229af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang // The first two bytes of the service data are service data UUID. 2306d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT; 2316d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos, 2326d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang serviceUuidLength); 2336d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang serviceDataUuid = BluetoothUuid.parseUuidFrom(serviceDataUuidBytes); 2346d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang break; 2356d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: 2366d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang manufacturerSpecificData = extractBytes(scanRecord, currentPos, 2376d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang dataLength); 2386d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // The first two bytes of the manufacturer specific data are 2396d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // manufacturer ids in little endian. 2406d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang manufacturerId = ((manufacturerSpecificData[1] & 0xFF) << 8) + 2416d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang (manufacturerSpecificData[0] & 0xFF); 2426d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang break; 2436d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang default: 2446d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // Just ignore, we don't handle such data type. 2456d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang break; 2466d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2476d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang currentPos += dataLength; 2486d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2496d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 2506d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang if (serviceUuids.isEmpty()) { 2516d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang serviceUuids = null; 2526d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2536d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return new ScanRecord(serviceUuids, serviceDataUuid, serviceData, 2546d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang manufacturerId, manufacturerSpecificData, advertiseFlag, txPowerLevel, 255685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang localName, scanRecord); 2566d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } catch (IndexOutOfBoundsException e) { 2576d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord)); 2586d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return null; 2596d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2606d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2616d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 262685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang @Override 263685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang public String toString() { 264685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids 265685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang + ", mManufacturerId=" + mManufacturerId + ", mManufacturerSpecificData=" 266685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang + Arrays.toString(mManufacturerSpecificData) + ", mServiceDataUuid=" 267685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang + mServiceDataUuid + ", mServiceData=" + Arrays.toString(mServiceData) 268685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]"; 269685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang } 270685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang 271685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang 272af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang // Parse service UUIDs. 2736d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static int parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength, 2746d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang int uuidLength, List<ParcelUuid> serviceUuids) { 2756d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang while (dataLength > 0) { 2766d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang byte[] uuidBytes = extractBytes(scanRecord, currentPos, 2776d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang uuidLength); 2786d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang serviceUuids.add(BluetoothUuid.parseUuidFrom(uuidBytes)); 2796d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang dataLength -= uuidLength; 2806d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang currentPos += uuidLength; 2816d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2826d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return currentPos; 2836d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2846d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 2856d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // Helper method to extract bytes from byte array. 2866d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static byte[] extractBytes(byte[] scanRecord, int start, int length) { 2876d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang byte[] bytes = new byte[length]; 2886d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang System.arraycopy(scanRecord, start, bytes, 0, length); 2896d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return bytes; 2906d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2916d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang} 292