diff --git a/library/src/main/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtils.java b/library/src/main/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtils.java index c872f82..0f245d4 100644 --- a/library/src/main/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtils.java +++ b/library/src/main/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtils.java @@ -58,14 +58,14 @@ public static List parseScanRecordAsList(final byte[] scanRecord) { int index = 0; while (index < scanRecord.length) { - final int length = scanRecord[index++]; + final int length = scanRecord[index++] & 0xFF; //Done once we run out of records - if (length == 0) break; + if (length < 1) break; final int type = ByteUtils.getIntFromByte(scanRecord[index]); //Done if our record isn't a valid type - if (type == 0) break; + if (type < 1) break; final byte[] data = Arrays.copyOfRange(scanRecord, index + 1, index + length); @@ -84,14 +84,14 @@ public static Map parseScanRecordAsMap(final byte[] scanRecor int index = 0; while (index < scanRecord.length) { - final int length = scanRecord[index++]; + final int length = scanRecord[index++] & 0xFF; //Done once we run out of records - if (length == 0) break; + if (length < 1) break; final int type = ByteUtils.getIntFromByte(scanRecord[index]); //Done if our record isn't a valid type - if (type == 0) break; + if (type < 1) break; final byte[] data = Arrays.copyOfRange(scanRecord, index + 1, index + length); @@ -109,14 +109,14 @@ public static SparseArray parseScanRecordAsSparseArray(final byte[] sc int index = 0; while (index < scanRecord.length) { - final int length = scanRecord[index++]; + final int length = scanRecord[index++] & 0xFF; //Done once we run out of records - if (length == 0) break; + if (length < 1) break; final int type = ByteUtils.getIntFromByte(scanRecord[index]); //Done if our record isn't a valid type - if (type == 0) break; + if (type < 1) break; final byte[] data = Arrays.copyOfRange(scanRecord, index + 1, index + length); diff --git a/library/src/test/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtilsTest.java b/library/src/test/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtilsTest.java index d528dd8..35b7afb 100644 --- a/library/src/test/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtilsTest.java +++ b/library/src/test/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtilsTest.java @@ -1,23 +1,21 @@ package uk.co.alt236.bluetoothlelib.util; -import junit.framework.TestCase; - import java.util.List; import java.util.Map; - +import junit.framework.TestCase; import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord; /** - * + * Advertisement records related tests. */ public class AdRecordUtilsTest extends TestCase { - private static final byte[] NON_IBEACON = - {2, 1, 26, 11, -1, 76, 0, 9, 6, 3, -32, -64, -88, - 1, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + private static final byte[] NON_IBEACON = { + 2, 1, 26, 11, -1, 76, 0, 9, 6, 3, -32, -64, -88, 1, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 + }; - public void testParseScanRecordAsList() throws Exception { + public void testParseScanRecordAsList() { final List adRecords = AdRecordUtils.parseScanRecordAsList(NON_IBEACON); assertNotNull(adRecords); assertEquals(2, adRecords.size()); @@ -31,7 +29,7 @@ public void testParseScanRecordAsList() throws Exception { assertEquals(11, adRecords.get(1).getLength()); } - public void testParseScanRecordAsMap() throws Exception { + public void testParseScanRecordAsMap() { final Map adRecords = AdRecordUtils.parseScanRecordAsMap(NON_IBEACON); assertNotNull(adRecords); assertEquals(2, adRecords.size()); @@ -45,7 +43,27 @@ public void testParseScanRecordAsMap() throws Exception { assertEquals(11, adRecords.get(type).getLength()); } - public void testParseScanRecordAsSparseArray() throws Exception { + /** + * Test negative record lengths. In Java all primitive types are signed, and we could receive + * a negative length in the record. Thus, we always have to convert it into unsigned. + */ + public void testNegativeRecordLength() { + // (byte)0x80 & 0xFF = 170. In Java (byte)0x80 = -128. + Map adRecords = + AdRecordUtils.parseScanRecordAsMap(new byte[] { -128, 1, 0 }); + assertNotNull(adRecords); + assertEquals(1, adRecords.size()); + assertEquals(128, adRecords.get(1).getLength()); + + // (byte)0xAA & 0xFF = 170. In Java (byte)0xAA = -86. + adRecords = + AdRecordUtils.parseScanRecordAsMap(new byte[] { -86, 1, 0 }); + assertNotNull(adRecords); + assertEquals(1, adRecords.size()); + assertEquals(170, adRecords.get(1).getLength()); + } + + public void testParseScanRecordAsSparseArray() { // // Cannot be tested here as it relies on Android code... //