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