1 /* 2 * Copyright (C) 2009 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; 18 19 import android.os.ParcelUuid; 20 21 import java.nio.ByteBuffer; 22 import java.nio.ByteOrder; 23 import java.util.Arrays; 24 import java.util.HashSet; 25 import java.util.UUID; 26 27 /** 28 * Static helper methods and constants to decode the ParcelUuid of remote devices. 29 * @hide 30 */ 31 public final class BluetoothUuid { 32 33 /* See Bluetooth Assigned Numbers document - SDP section, to get the values of UUIDs 34 * for the various services. 35 * 36 * The following 128 bit values are calculated as: 37 * uuid * 2^96 + BASE_UUID 38 */ 39 public static final ParcelUuid AudioSink = 40 ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"); 41 public static final ParcelUuid AudioSource = 42 ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB"); 43 public static final ParcelUuid AdvAudioDist = 44 ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB"); 45 public static final ParcelUuid HSP = 46 ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB"); 47 public static final ParcelUuid HSP_AG = 48 ParcelUuid.fromString("00001112-0000-1000-8000-00805F9B34FB"); 49 public static final ParcelUuid Handsfree = 50 ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB"); 51 public static final ParcelUuid Handsfree_AG = 52 ParcelUuid.fromString("0000111F-0000-1000-8000-00805F9B34FB"); 53 public static final ParcelUuid AvrcpController = 54 ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB"); 55 public static final ParcelUuid AvrcpTarget = 56 ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB"); 57 public static final ParcelUuid ObexObjectPush = 58 ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb"); 59 public static final ParcelUuid Hid = 60 ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb"); 61 public static final ParcelUuid Hogp = 62 ParcelUuid.fromString("00001812-0000-1000-8000-00805f9b34fb"); 63 public static final ParcelUuid PANU = 64 ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB"); 65 public static final ParcelUuid NAP = 66 ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB"); 67 public static final ParcelUuid BNEP = 68 ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB"); 69 public static final ParcelUuid PBAP_PCE = 70 ParcelUuid.fromString("0000112e-0000-1000-8000-00805F9B34FB"); 71 public static final ParcelUuid PBAP_PSE = 72 ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB"); 73 public static final ParcelUuid MAP = 74 ParcelUuid.fromString("00001134-0000-1000-8000-00805F9B34FB"); 75 public static final ParcelUuid MNS = 76 ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB"); 77 public static final ParcelUuid MAS = 78 ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB"); 79 80 public static final ParcelUuid BASE_UUID = 81 ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); 82 83 /** Length of bytes for 16 bit UUID */ 84 public static final int UUID_BYTES_16_BIT = 2; 85 /** Length of bytes for 32 bit UUID */ 86 public static final int UUID_BYTES_32_BIT = 4; 87 /** Length of bytes for 128 bit UUID */ 88 public static final int UUID_BYTES_128_BIT = 16; 89 90 public static final ParcelUuid[] RESERVED_UUIDS = { 91 AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, 92 ObexObjectPush, PANU, NAP, MAP, MNS, MAS}; 93 isAudioSource(ParcelUuid uuid)94 public static boolean isAudioSource(ParcelUuid uuid) { 95 return uuid.equals(AudioSource); 96 } 97 isAudioSink(ParcelUuid uuid)98 public static boolean isAudioSink(ParcelUuid uuid) { 99 return uuid.equals(AudioSink); 100 } 101 isAdvAudioDist(ParcelUuid uuid)102 public static boolean isAdvAudioDist(ParcelUuid uuid) { 103 return uuid.equals(AdvAudioDist); 104 } 105 isHandsfree(ParcelUuid uuid)106 public static boolean isHandsfree(ParcelUuid uuid) { 107 return uuid.equals(Handsfree); 108 } 109 isHeadset(ParcelUuid uuid)110 public static boolean isHeadset(ParcelUuid uuid) { 111 return uuid.equals(HSP); 112 } 113 isAvrcpController(ParcelUuid uuid)114 public static boolean isAvrcpController(ParcelUuid uuid) { 115 return uuid.equals(AvrcpController); 116 } 117 isAvrcpTarget(ParcelUuid uuid)118 public static boolean isAvrcpTarget(ParcelUuid uuid) { 119 return uuid.equals(AvrcpTarget); 120 } 121 isInputDevice(ParcelUuid uuid)122 public static boolean isInputDevice(ParcelUuid uuid) { 123 return uuid.equals(Hid); 124 } 125 isPanu(ParcelUuid uuid)126 public static boolean isPanu(ParcelUuid uuid) { 127 return uuid.equals(PANU); 128 } 129 isNap(ParcelUuid uuid)130 public static boolean isNap(ParcelUuid uuid) { 131 return uuid.equals(NAP); 132 } 133 isBnep(ParcelUuid uuid)134 public static boolean isBnep(ParcelUuid uuid) { 135 return uuid.equals(BNEP); 136 } isMap(ParcelUuid uuid)137 public static boolean isMap(ParcelUuid uuid) { 138 return uuid.equals(MAP); 139 } isMns(ParcelUuid uuid)140 public static boolean isMns(ParcelUuid uuid) { 141 return uuid.equals(MNS); 142 } isMas(ParcelUuid uuid)143 public static boolean isMas(ParcelUuid uuid) { 144 return uuid.equals(MAS); 145 } 146 147 /** 148 * Returns true if ParcelUuid is present in uuidArray 149 * 150 * @param uuidArray - Array of ParcelUuids 151 * @param uuid 152 */ isUuidPresent(ParcelUuid[] uuidArray, ParcelUuid uuid)153 public static boolean isUuidPresent(ParcelUuid[] uuidArray, ParcelUuid uuid) { 154 if ((uuidArray == null || uuidArray.length == 0) && uuid == null) 155 return true; 156 157 if (uuidArray == null) 158 return false; 159 160 for (ParcelUuid element: uuidArray) { 161 if (element.equals(uuid)) return true; 162 } 163 return false; 164 } 165 166 /** 167 * Returns true if there any common ParcelUuids in uuidA and uuidB. 168 * 169 * @param uuidA - List of ParcelUuids 170 * @param uuidB - List of ParcelUuids 171 * 172 */ containsAnyUuid(ParcelUuid[] uuidA, ParcelUuid[] uuidB)173 public static boolean containsAnyUuid(ParcelUuid[] uuidA, ParcelUuid[] uuidB) { 174 if (uuidA == null && uuidB == null) return true; 175 176 if (uuidA == null) { 177 return uuidB.length == 0 ? true : false; 178 } 179 180 if (uuidB == null) { 181 return uuidA.length == 0 ? true : false; 182 } 183 184 HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid> (Arrays.asList(uuidA)); 185 for (ParcelUuid uuid: uuidB) { 186 if (uuidSet.contains(uuid)) return true; 187 } 188 return false; 189 } 190 191 /** 192 * Returns true if all the ParcelUuids in ParcelUuidB are present in 193 * ParcelUuidA 194 * 195 * @param uuidA - Array of ParcelUuidsA 196 * @param uuidB - Array of ParcelUuidsB 197 * 198 */ containsAllUuids(ParcelUuid[] uuidA, ParcelUuid[] uuidB)199 public static boolean containsAllUuids(ParcelUuid[] uuidA, ParcelUuid[] uuidB) { 200 if (uuidA == null && uuidB == null) return true; 201 202 if (uuidA == null) { 203 return uuidB.length == 0 ? true : false; 204 } 205 206 if (uuidB == null) return true; 207 208 HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid> (Arrays.asList(uuidA)); 209 for (ParcelUuid uuid: uuidB) { 210 if (!uuidSet.contains(uuid)) return false; 211 } 212 return true; 213 } 214 215 /** 216 * Extract the Service Identifier or the actual uuid from the Parcel Uuid. 217 * For example, if 0000110B-0000-1000-8000-00805F9B34FB is the parcel Uuid, 218 * this function will return 110B 219 * @param parcelUuid 220 * @return the service identifier. 221 */ getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid)222 public static int getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid) { 223 UUID uuid = parcelUuid.getUuid(); 224 long value = (uuid.getMostSignificantBits() & 0x0000FFFF00000000L) >>> 32; 225 return (int)value; 226 } 227 228 /** 229 * Parse UUID from bytes. The {@code uuidBytes} can represent a 16-bit, 32-bit or 128-bit UUID, 230 * but the returned UUID is always in 128-bit format. 231 * Note UUID is little endian in Bluetooth. 232 * 233 * @param uuidBytes Byte representation of uuid. 234 * @return {@link ParcelUuid} parsed from bytes. 235 * @throws IllegalArgumentException If the {@code uuidBytes} cannot be parsed. 236 */ parseUuidFrom(byte[] uuidBytes)237 public static ParcelUuid parseUuidFrom(byte[] uuidBytes) { 238 if (uuidBytes == null) { 239 throw new IllegalArgumentException("uuidBytes cannot be null"); 240 } 241 int length = uuidBytes.length; 242 if (length != UUID_BYTES_16_BIT && length != UUID_BYTES_32_BIT && 243 length != UUID_BYTES_128_BIT) { 244 throw new IllegalArgumentException("uuidBytes length invalid - " + length); 245 } 246 247 // Construct a 128 bit UUID. 248 if (length == UUID_BYTES_128_BIT) { 249 ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN); 250 long msb = buf.getLong(8); 251 long lsb = buf.getLong(0); 252 return new ParcelUuid(new UUID(msb, lsb)); 253 } 254 255 // For 16 bit and 32 bit UUID we need to convert them to 128 bit value. 256 // 128_bit_value = uuid * 2^96 + BASE_UUID 257 long shortUuid; 258 if (length == UUID_BYTES_16_BIT) { 259 shortUuid = uuidBytes[0] & 0xFF; 260 shortUuid += (uuidBytes[1] & 0xFF) << 8; 261 } else { 262 shortUuid = uuidBytes[0] & 0xFF ; 263 shortUuid += (uuidBytes[1] & 0xFF) << 8; 264 shortUuid += (uuidBytes[2] & 0xFF) << 16; 265 shortUuid += (uuidBytes[3] & 0xFF) << 24; 266 } 267 long msb = BASE_UUID.getUuid().getMostSignificantBits() + (shortUuid << 32); 268 long lsb = BASE_UUID.getUuid().getLeastSignificantBits(); 269 return new ParcelUuid(new UUID(msb, lsb)); 270 } 271 272 /** 273 * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid. 274 * 275 * @param parcelUuid 276 * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise. 277 */ is16BitUuid(ParcelUuid parcelUuid)278 public static boolean is16BitUuid(ParcelUuid parcelUuid) { 279 UUID uuid = parcelUuid.getUuid(); 280 if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { 281 return false; 282 } 283 return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L); 284 } 285 286 287 /** 288 * Check whether the given parcelUuid can be converted to 32 bit bluetooth uuid. 289 * 290 * @param parcelUuid 291 * @return true if the parcelUuid can be converted to 32 bit uuid, false otherwise. 292 */ is32BitUuid(ParcelUuid parcelUuid)293 public static boolean is32BitUuid(ParcelUuid parcelUuid) { 294 UUID uuid = parcelUuid.getUuid(); 295 if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { 296 return false; 297 } 298 if (is16BitUuid(parcelUuid)) { 299 return false; 300 } 301 return ((uuid.getMostSignificantBits() & 0xFFFFFFFFL) == 0x1000L); 302 } 303 } 304