Loading android/app/src/com/android/bluetooth/gatt/GattService.java +9 −8 Original line number Diff line number Diff line Loading @@ -42,6 +42,8 @@ import android.util.Log; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.util.NumberUtils; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -1029,27 +1031,26 @@ public class GattService extends ProfileService { private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { if (DBG) Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); Set<ScanResult> results = new HashSet<ScanResult>(numRecords); long now = SystemClock.elapsedRealtimeNanos(); for (int i = 0; i < numRecords; ++i) { byte[] record = extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE); byte[] address = extractBytes(record, 0, 6); // TODO: remove temp hack. reverse(address); BluetoothDevice device = mAdapter.getRemoteDevice(address); int rssi = record[8]; // Timestamp is in every 50 ms. long timestampNanos = parseTimestampNanos(extractBytes(record, 9, 2)); long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), rssi, timestampNanos)); } return results; } private long parseTimestampNanos(byte[] data) { long timestampUnit = data[1] & 0xFF << 8 + data[0]; long timestampNanos = SystemClock.elapsedRealtimeNanos() - TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); return timestampNanos; @VisibleForTesting long parseTimestampNanos(byte[] data) { long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data); // Timestamp is in every 50 ms. return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); } private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { Loading android/app/src/com/android/bluetooth/util/NumberUtils.java 0 → 100644 +46 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.util; /** * Utility for parsing numbers in Bluetooth. */ public class NumberUtils { /** * Convert a byte to unsigned int. */ public static int unsignedByteToInt(byte b) { return b & 0xFF; } /** * Convert a little endian byte array to integer. */ public static int littleEndianByteArrayToInt(byte[] bytes) { int length = bytes.length; if (length == 0) { return 0; } int result = 0; for (int i = length - 1; i >= 0; i--) { int value = unsignedByteToInt(bytes[i]); result += (value << (i * 8)); } return result; } } android/app/tests/src/com/android/bluetooth/gatt/GattServiceTest.java 0 → 100644 +22 −0 Original line number Diff line number Diff line package com.android.bluetooth.gatt; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import com.android.bluetooth.gatt.GattService; /** * Test cases for {@link GattService}. */ public class GattServiceTest extends AndroidTestCase { @SmallTest public void testParseBatchTimestamp() { GattService service = new GattService(); long timestampNanos = service.parseTimestampNanos(new byte[] { -54, 7 }); assertEquals(99700000000L, timestampNanos); } } android/app/tests/src/com/android/bluetooth/util/NumberUtilsTest.java 0 → 100644 +43 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.util; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; /** * Tests for {@link NumberUtils}. */ public class NumberUtilsTest extends AndroidTestCase { @SmallTest public static void testUnsignedByteToInt() { assertEquals(0, NumberUtils.unsignedByteToInt((byte) 0)); assertEquals(19, NumberUtils.unsignedByteToInt((byte) 19)); assertEquals(154, NumberUtils.unsignedByteToInt((byte) 154)); } @SmallTest public void testLittleEndianByteArrayToInt() { assertEquals(1, NumberUtils.littleEndianByteArrayToInt(new byte[] { 1 })); assertEquals(513, NumberUtils.littleEndianByteArrayToInt(new byte[] { 1, 2 })); assertEquals(197121, NumberUtils.littleEndianByteArrayToInt(new byte[] { 1, 2, 3 })); } } Loading
android/app/src/com/android/bluetooth/gatt/GattService.java +9 −8 Original line number Diff line number Diff line Loading @@ -42,6 +42,8 @@ import android.util.Log; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.util.NumberUtils; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -1029,27 +1031,26 @@ public class GattService extends ProfileService { private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { if (DBG) Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); Set<ScanResult> results = new HashSet<ScanResult>(numRecords); long now = SystemClock.elapsedRealtimeNanos(); for (int i = 0; i < numRecords; ++i) { byte[] record = extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE); byte[] address = extractBytes(record, 0, 6); // TODO: remove temp hack. reverse(address); BluetoothDevice device = mAdapter.getRemoteDevice(address); int rssi = record[8]; // Timestamp is in every 50 ms. long timestampNanos = parseTimestampNanos(extractBytes(record, 9, 2)); long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), rssi, timestampNanos)); } return results; } private long parseTimestampNanos(byte[] data) { long timestampUnit = data[1] & 0xFF << 8 + data[0]; long timestampNanos = SystemClock.elapsedRealtimeNanos() - TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); return timestampNanos; @VisibleForTesting long parseTimestampNanos(byte[] data) { long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data); // Timestamp is in every 50 ms. return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); } private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { Loading
android/app/src/com/android/bluetooth/util/NumberUtils.java 0 → 100644 +46 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.util; /** * Utility for parsing numbers in Bluetooth. */ public class NumberUtils { /** * Convert a byte to unsigned int. */ public static int unsignedByteToInt(byte b) { return b & 0xFF; } /** * Convert a little endian byte array to integer. */ public static int littleEndianByteArrayToInt(byte[] bytes) { int length = bytes.length; if (length == 0) { return 0; } int result = 0; for (int i = length - 1; i >= 0; i--) { int value = unsignedByteToInt(bytes[i]); result += (value << (i * 8)); } return result; } }
android/app/tests/src/com/android/bluetooth/gatt/GattServiceTest.java 0 → 100644 +22 −0 Original line number Diff line number Diff line package com.android.bluetooth.gatt; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import com.android.bluetooth.gatt.GattService; /** * Test cases for {@link GattService}. */ public class GattServiceTest extends AndroidTestCase { @SmallTest public void testParseBatchTimestamp() { GattService service = new GattService(); long timestampNanos = service.parseTimestampNanos(new byte[] { -54, 7 }); assertEquals(99700000000L, timestampNanos); } }
android/app/tests/src/com/android/bluetooth/util/NumberUtilsTest.java 0 → 100644 +43 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.util; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; /** * Tests for {@link NumberUtils}. */ public class NumberUtilsTest extends AndroidTestCase { @SmallTest public static void testUnsignedByteToInt() { assertEquals(0, NumberUtils.unsignedByteToInt((byte) 0)); assertEquals(19, NumberUtils.unsignedByteToInt((byte) 19)); assertEquals(154, NumberUtils.unsignedByteToInt((byte) 154)); } @SmallTest public void testLittleEndianByteArrayToInt() { assertEquals(1, NumberUtils.littleEndianByteArrayToInt(new byte[] { 1 })); assertEquals(513, NumberUtils.littleEndianByteArrayToInt(new byte[] { 1, 2 })); assertEquals(197121, NumberUtils.littleEndianByteArrayToInt(new byte[] { 1, 2, 3 })); } }