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