docs: @Nullable
  	/* package */ static ScanRecord parseFromBytes(@Nullable final byte[] scanRecord) {
  		if (scanRecord == null) {
  			return null;
  		}
  
  		int currentPos = 0;
  		int advertiseFlag = -1;
  		int txPowerLevel = Integer.MIN_VALUE;
  		String localName = null;
  		List<ParcelUuid> serviceUuids = null;
  		SparseArray<byte[]> manufacturerData = null;
  		Map<ParcelUuid, byte[]> serviceData = null;
  
  		try {
  			while (currentPos < scanRecord.length) {
  				// length is unsigned int.
  				final int length = scanRecord[currentPos++] & 0xFF;
  				if (length == 0) {
  					break;
  				}
  				// Note the length includes the length of the field type itself.
  				final int dataLength = length - 1;
  				// fieldType is unsigned int.
  				final int fieldType = scanRecord[currentPos++] & 0xFF;
  				switch (fieldType) {
  					case DATA_TYPE_FLAGS:
  						advertiseFlag = scanRecord[currentPos] & 0xFF;
  						break;
  					case DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL:
  					case DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE:
  						if (serviceUuids == null)
  							serviceUuids = new ArrayList<>();
  						parseServiceUuid(scanRecord, currentPos,
  								dataLength, BluetoothUuid.UUID_BYTES_16_BIT, serviceUuids);
  						break;
  					case DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL:
  					case DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE:
  						if (serviceUuids == null)
  							serviceUuids = new ArrayList<>();
  						parseServiceUuid(scanRecord, currentPos, dataLength,
  								BluetoothUuid.UUID_BYTES_32_BIT, serviceUuids);
  						break;
  					case DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL:
  					case DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE:
  						if (serviceUuids == null)
  							serviceUuids = new ArrayList<>();
  						parseServiceUuid(scanRecord, currentPos, dataLength,
  								BluetoothUuid.UUID_BYTES_128_BIT, serviceUuids);
  						break;
  					case DATA_TYPE_LOCAL_NAME_SHORT:
  					case DATA_TYPE_LOCAL_NAME_COMPLETE:
  						localName = new String(
  								extractBytes(scanRecord, currentPos, dataLength));
  						break;
  					case DATA_TYPE_TX_POWER_LEVEL:
  						txPowerLevel = scanRecord[currentPos];
  						break;
  					case DATA_TYPE_SERVICE_DATA_16_BIT:
  					case DATA_TYPE_SERVICE_DATA_32_BIT:
  					case DATA_TYPE_SERVICE_DATA_128_BIT:
  						int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT;
  						if (fieldType == DATA_TYPE_SERVICE_DATA_32_BIT) {
  							serviceUuidLength = BluetoothUuid.UUID_BYTES_32_BIT;
  						} else if (fieldType == DATA_TYPE_SERVICE_DATA_128_BIT) {
  							serviceUuidLength = BluetoothUuid.UUID_BYTES_128_BIT;
  						}
  
  						final byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos,
  								serviceUuidLength);
  						final ParcelUuid serviceDataUuid = BluetoothUuid.parseUuidFrom(
  								serviceDataUuidBytes);
  						final byte[] serviceDataArray = extractBytes(scanRecord,
  								currentPos + serviceUuidLength, dataLength - serviceUuidLength);
  						if (serviceData == null)
  							serviceData = new HashMap<>();
  						serviceData.put(serviceDataUuid, serviceDataArray);
  						break;
  					case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
  						// The first two bytes of the manufacturer specific data are
  						// manufacturer ids in little endian.
  						final int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) +
  								(scanRecord[currentPos] & 0xFF);
  						final byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2,
  								dataLength - 2);
  						if (manufacturerData == null)
  							manufacturerData = new SparseArray<>();
  						manufacturerData.put(manufacturerId, manufacturerDataBytes);
  						break;
  					default:
  						// Just ignore, we don't handle such data type.
  						break;
  				}
  				currentPos += dataLength;
  			}
  
  			return new ScanRecord(serviceUuids, manufacturerData, serviceData,
  					advertiseFlag, txPowerLevel, localName, scanRecord);
  		} catch (final Exception e) {
  			Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord));
  			// As the record is invalid, ignore all the parsed results for this packet
  			// and return an empty record with raw scanRecord bytes in results
  			return new ScanRecord(null, null, null,
  					-1, Integer.MIN_VALUE, null, scanRecord);
  		}
  	}