diff options
-rw-r--r-- | core/java/android/bluetooth/BluetoothUuid.java | 63 | ||||
-rw-r--r-- | core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java | 50 |
2 files changed, 108 insertions, 5 deletions
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java index 4b28516..ab53fb0 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -18,6 +18,8 @@ package android.bluetooth; import android.os.ParcelUuid; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.Arrays; import java.util.HashSet; import java.util.UUID; @@ -76,6 +78,12 @@ public final class BluetoothUuid { public static final ParcelUuid BASE_UUID = ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); + /** Length of bytes for 16 bit UUID */ + public static final int UUID_BYTES_16_BIT = 2; + /** Length of bytes for 32 bit UUID */ + public static final int UUID_BYTES_32_BIT = 4; + /** Length of bytes for 128 bit UUID */ + public static final int UUID_BYTES_128_BIT = 16; public static final ParcelUuid[] RESERVED_UUIDS = { AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, @@ -216,15 +224,60 @@ public final class BluetoothUuid { } /** + * Parse UUID from bytes. The {@code uuidBytes} can represent a 16-bit, 32-bit or 128-bit UUID, + * but the returned UUID is always in 128-bit format. + * Note UUID is little endian in Bluetooth. + * + * @param uuidBytes Byte representation of uuid. + * @return {@link ParcelUuid} parsed from bytes. + * @throws IllegalArgumentException If the {@code uuidBytes} cannot be parsed. + */ + public static ParcelUuid parseUuidFrom(byte[] uuidBytes) { + if (uuidBytes == null) { + throw new IllegalArgumentException("uuidBytes cannot be null"); + } + int length = uuidBytes.length; + if (length != UUID_BYTES_16_BIT && length != UUID_BYTES_32_BIT && + length != UUID_BYTES_128_BIT) { + throw new IllegalArgumentException("uuidBytes length invalid - " + length); + } + + // Construct a 128 bit UUID. + if (length == UUID_BYTES_128_BIT) { + ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN); + long msb = buf.getLong(8); + long lsb = buf.getLong(0); + return new ParcelUuid(new UUID(msb, lsb)); + } + + // For 16 bit and 32 bit UUID we need to convert them to 128 bit value. + // 128_bit_value = uuid * 2^96 + BASE_UUID + long shortUuid; + if (length == UUID_BYTES_16_BIT) { + shortUuid = uuidBytes[0] & 0xFF; + shortUuid += (uuidBytes[1] & 0xFF) << 8; + } else { + shortUuid = uuidBytes[0] & 0xFF ; + shortUuid += (uuidBytes[1] & 0xFF) << 8; + shortUuid += (uuidBytes[2] & 0xFF) << 16; + shortUuid += (uuidBytes[3] & 0xFF) << 24; + } + long msb = BASE_UUID.getUuid().getMostSignificantBits() + (shortUuid << 32); + long lsb = BASE_UUID.getUuid().getLeastSignificantBits(); + return new ParcelUuid(new UUID(msb, lsb)); + } + + /** * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid. + * * @param parcelUuid * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise. */ public static boolean isShortUuid(ParcelUuid parcelUuid) { - UUID uuid = parcelUuid.getUuid(); - if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { - return false; - } - return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L); + UUID uuid = parcelUuid.getUuid(); + if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { + return false; + } + return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L); } } diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java new file mode 100644 index 0000000..0f3ea0e --- /dev/null +++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java @@ -0,0 +1,50 @@ +/* + * 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 android.bluetooth; + +import android.os.ParcelUuid; +import android.test.suitebuilder.annotation.SmallTest; + +import junit.framework.TestCase; + +/** + * Unit test cases for {@link BluetoothUuid}. + * <p> + * To run this test, use adb shell am instrument -e class 'android.bluetooth.BluetoothUuidTest' -w + * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner' + */ +public class BluetoothUuidTest extends TestCase { + + @SmallTest + public void testUuidParser() { + byte[] uuid16 = new byte[] { + 0x0B, 0x11 }; + assertEquals(ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"), + BluetoothUuid.parseUuidFrom(uuid16)); + + byte[] uuid32 = new byte[] { + 0x0B, 0x11, 0x33, (byte) 0xFE }; + assertEquals(ParcelUuid.fromString("FE33110B-0000-1000-8000-00805F9B34FB"), + BluetoothUuid.parseUuidFrom(uuid32)); + + byte[] uuid128 = new byte[] { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, (byte) 0xFF }; + assertEquals(ParcelUuid.fromString("FF0F0E0D-0C0B-0A09-0807-0060504030201"), + BluetoothUuid.parseUuidFrom(uuid128)); + } +} |