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.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.SuppressLint; 22 import android.annotation.SystemApi; 23 import android.compat.annotation.UnsupportedAppUsage; 24 import android.os.ParcelUuid; 25 26 import java.nio.ByteBuffer; 27 import java.nio.ByteOrder; 28 import java.util.Arrays; 29 import java.util.HashSet; 30 import java.util.UUID; 31 32 /** 33 * Static helper methods and constants to decode the ParcelUuid of remote devices. Bluetooth service 34 * UUIDs are defined in the SDP section of the Bluetooth Assigned Numbers document. The constant 128 35 * bit values in this class are calculated as: uuid * 2^96 + {@link #BASE_UUID}. 36 * 37 * @hide 38 */ 39 @SystemApi 40 @SuppressLint("AndroidFrameworkBluetoothPermission") 41 public final class BluetoothUuid { 42 43 /** 44 * UUID corresponding to the Audio sink role (also referred to as the A2DP sink role). 45 * 46 * @hide 47 */ 48 @NonNull @SystemApi 49 public static final ParcelUuid A2DP_SINK = 50 ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"); 51 52 /** 53 * UUID corresponding to the Audio source role (also referred to as the A2DP source role). 54 * 55 * @hide 56 */ 57 @NonNull @SystemApi 58 public static final ParcelUuid A2DP_SOURCE = 59 ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB"); 60 61 /** 62 * UUID corresponding to the Advanced Audio Distribution Profile (A2DP). 63 * 64 * @hide 65 */ 66 @NonNull @SystemApi 67 public static final ParcelUuid ADV_AUDIO_DIST = 68 ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB"); 69 70 /** 71 * UUID corresponding to the Headset Profile (HSP). 72 * 73 * @hide 74 */ 75 @NonNull @SystemApi 76 public static final ParcelUuid HSP = 77 ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB"); 78 79 /** 80 * UUID corresponding to the Headset Profile (HSP) Audio Gateway role. 81 * 82 * @hide 83 */ 84 @NonNull @SystemApi 85 public static final ParcelUuid HSP_AG = 86 ParcelUuid.fromString("00001112-0000-1000-8000-00805F9B34FB"); 87 88 /** 89 * UUID corresponding to the Hands-Free Profile (HFP). 90 * 91 * @hide 92 */ 93 @NonNull @SystemApi 94 public static final ParcelUuid HFP = 95 ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB"); 96 97 /** 98 * UUID corresponding to the Hands-Free Profile (HFP) Audio Gateway role. 99 * 100 * @hide 101 */ 102 @NonNull @SystemApi 103 public static final ParcelUuid HFP_AG = 104 ParcelUuid.fromString("0000111F-0000-1000-8000-00805F9B34FB"); 105 106 /** 107 * UUID corresponding to the Audio Video Remote Control Profile (AVRCP). 108 * 109 * @hide 110 */ 111 @NonNull @SystemApi 112 public static final ParcelUuid AVRCP = 113 ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB"); 114 115 /** 116 * UUID corresponding to the Audio Video Remote Control Profile (AVRCP) controller role. 117 * 118 * @hide 119 */ 120 @NonNull @SystemApi 121 public static final ParcelUuid AVRCP_CONTROLLER = 122 ParcelUuid.fromString("0000110F-0000-1000-8000-00805F9B34FB"); 123 124 /** 125 * UUID corresponding to the Audio Video Remote Control Profile (AVRCP) target role. 126 * 127 * @hide 128 */ 129 @NonNull @SystemApi 130 public static final ParcelUuid AVRCP_TARGET = 131 ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB"); 132 133 /** 134 * UUID corresponding to the OBject EXchange (OBEX) Object Push Profile (OPP). 135 * 136 * @hide 137 */ 138 @NonNull @SystemApi 139 public static final ParcelUuid OBEX_OBJECT_PUSH = 140 ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb"); 141 142 /** 143 * UUID corresponding to the Human Interface Device (HID) profile. 144 * 145 * @hide 146 */ 147 @NonNull @SystemApi 148 public static final ParcelUuid HID = 149 ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb"); 150 151 /** 152 * UUID corresponding to the Human Interface Device over GATT Profile (HOGP). 153 * 154 * @hide 155 */ 156 @NonNull @SystemApi 157 public static final ParcelUuid HOGP = 158 ParcelUuid.fromString("00001812-0000-1000-8000-00805f9b34fb"); 159 160 /** 161 * UUID corresponding to the Personal Area Network User (PANU) role. 162 * 163 * @hide 164 */ 165 @NonNull @SystemApi 166 public static final ParcelUuid PANU = 167 ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB"); 168 169 /** 170 * UUID corresponding to the Network Access Point (NAP) role. 171 * 172 * @hide 173 */ 174 @NonNull @SystemApi 175 public static final ParcelUuid NAP = 176 ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB"); 177 178 /** 179 * UUID corresponding to the Bluetooth Network Encapsulation Protocol (BNEP). 180 * 181 * @hide 182 */ 183 @NonNull @SystemApi 184 public static final ParcelUuid BNEP = 185 ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB"); 186 187 /** 188 * UUID corresponding to the Phonebook Access Profile (PBAP) client role. 189 * 190 * @hide 191 */ 192 @NonNull @SystemApi 193 public static final ParcelUuid PBAP_PCE = 194 ParcelUuid.fromString("0000112e-0000-1000-8000-00805F9B34FB"); 195 196 /** 197 * UUID corresponding to the Phonebook Access Profile (PBAP) server role. 198 * 199 * @hide 200 */ 201 @NonNull @SystemApi 202 public static final ParcelUuid PBAP_PSE = 203 ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB"); 204 205 /** 206 * UUID corresponding to the Message Access Profile (MAP). 207 * 208 * @hide 209 */ 210 @NonNull @SystemApi 211 public static final ParcelUuid MAP = 212 ParcelUuid.fromString("00001134-0000-1000-8000-00805F9B34FB"); 213 214 /** 215 * UUID corresponding to the Message Notification Server (MNS) role. 216 * 217 * @hide 218 */ 219 @NonNull @SystemApi 220 public static final ParcelUuid MNS = 221 ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB"); 222 223 /** 224 * UUID corresponding to the Message Access Server (MAS) role. 225 * 226 * @hide 227 */ 228 @NonNull @SystemApi 229 public static final ParcelUuid MAS = 230 ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB"); 231 232 /** 233 * UUID corresponding to the Sim Access Profile (SAP). 234 * 235 * @hide 236 */ 237 @NonNull @SystemApi 238 public static final ParcelUuid SAP = 239 ParcelUuid.fromString("0000112D-0000-1000-8000-00805F9B34FB"); 240 241 /** 242 * UUID corresponding to the Hearing Aid Profile. 243 * 244 * @hide 245 */ 246 @NonNull @SystemApi 247 public static final ParcelUuid HEARING_AID = 248 ParcelUuid.fromString("0000FDF0-0000-1000-8000-00805f9b34fb"); 249 250 /** 251 * UUID corresponding to the Hearing Access Service (HAS). 252 * 253 * @hide 254 */ 255 @NonNull @SystemApi 256 public static final ParcelUuid HAS = 257 ParcelUuid.fromString("00001854-0000-1000-8000-00805F9B34FB"); 258 259 /** 260 * UUID corresponding to the Made For iPhone/iPod/iPad Hearing Aid Service (MFi HAS). 261 * 262 * @hide 263 */ 264 @NonNull @SystemApi 265 public static final ParcelUuid MFI_HAS = 266 ParcelUuid.fromString("7D74F4BD-C74A-4431-862C-CCE884371592"); 267 268 /** 269 * UUID corresponding to Audio Stream Control (also known as Bluetooth Low Energy Audio). 270 * 271 * @hide 272 */ 273 @NonNull @SystemApi 274 public static final ParcelUuid LE_AUDIO = 275 ParcelUuid.fromString("0000184E-0000-1000-8000-00805F9B34FB"); 276 277 /** 278 * UUID corresponding to the Device Identification Profile (DIP). 279 * 280 * @hide 281 */ 282 @NonNull @SystemApi 283 public static final ParcelUuid DIP = 284 ParcelUuid.fromString("00001200-0000-1000-8000-00805F9B34FB"); 285 286 /** 287 * UUID corresponding to the Volume Control Service. 288 * 289 * @hide 290 */ 291 @NonNull @SystemApi 292 public static final ParcelUuid VOLUME_CONTROL = 293 ParcelUuid.fromString("00001844-0000-1000-8000-00805F9B34FB"); 294 295 /** 296 * UUID corresponding to the Generic Media Control Service. 297 * 298 * @hide 299 */ 300 @NonNull @SystemApi 301 public static final ParcelUuid GENERIC_MEDIA_CONTROL = 302 ParcelUuid.fromString("00001849-0000-1000-8000-00805F9B34FB"); 303 304 /** 305 * UUID corresponding to the Gaming Audio Profile (GMAP). 306 * 307 * @hide 308 */ 309 @NonNull 310 public static final ParcelUuid GMAP = 311 ParcelUuid.fromString("00001858-0000-1000-8000-00805F9B34FB"); 312 313 /** 314 * UUID corresponding to the Media Control Service. 315 * 316 * @hide 317 */ 318 @NonNull @SystemApi 319 public static final ParcelUuid MEDIA_CONTROL = 320 ParcelUuid.fromString("00001848-0000-1000-8000-00805F9B34FB"); 321 322 /** 323 * UUID corresponding to the Coordinated Set Identification Service. 324 * 325 * @hide 326 */ 327 @NonNull @SystemApi 328 public static final ParcelUuid COORDINATED_SET = 329 ParcelUuid.fromString("00001846-0000-1000-8000-00805F9B34FB"); 330 331 /** 332 * UUID corresponding to the Common Audio Service. 333 * 334 * @hide 335 */ 336 @NonNull @SystemApi 337 public static final ParcelUuid CAP = 338 ParcelUuid.fromString("00001853-0000-1000-8000-00805F9B34FB"); 339 340 /** 341 * UUID corresponding to the Battery Service. 342 * 343 * @hide 344 */ 345 @NonNull 346 public static final ParcelUuid BATTERY = 347 ParcelUuid.fromString("0000180F-0000-1000-8000-00805F9B34FB"); 348 349 /** 350 * UUID corresponding to the Broadcast Audio Scan Service (also known as LE Audio Broadcast 351 * Assistant). 352 * 353 * @hide 354 */ 355 @NonNull @SystemApi 356 public static final ParcelUuid BASS = 357 ParcelUuid.fromString("0000184F-0000-1000-8000-00805F9B34FB"); 358 359 /** 360 * Telephony and Media Audio Profile (TMAP) UUID 361 * 362 * @hide 363 */ 364 @NonNull 365 public static final ParcelUuid TMAP = 366 ParcelUuid.fromString("00001855-0000-1000-8000-00805F9B34FB"); 367 368 /** @hide */ 369 @NonNull @SystemApi 370 public static final ParcelUuid BASE_UUID = 371 ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); 372 373 /** 374 * Length of bytes for 16 bit UUID 375 * 376 * @hide 377 */ 378 @SystemApi public static final int UUID_BYTES_16_BIT = 2; 379 380 /** 381 * Length of bytes for 32 bit UUID 382 * 383 * @hide 384 */ 385 @SystemApi public static final int UUID_BYTES_32_BIT = 4; 386 387 /** 388 * Length of bytes for 128 bit UUID 389 * 390 * @hide 391 */ 392 @SystemApi public static final int UUID_BYTES_128_BIT = 16; 393 394 /** 395 * Returns true if there any common ParcelUuids in uuidA and uuidB. 396 * 397 * @param uuidA - List of ParcelUuids 398 * @param uuidB - List of ParcelUuids 399 * @hide 400 */ 401 @SystemApi containsAnyUuid( @ullable ParcelUuid[] uuidA, @Nullable ParcelUuid[] uuidB)402 public static boolean containsAnyUuid( 403 @Nullable ParcelUuid[] uuidA, @Nullable ParcelUuid[] uuidB) { 404 if (uuidA == null && uuidB == null) return true; 405 406 if (uuidA == null) { 407 return uuidB.length == 0; 408 } 409 410 if (uuidB == null) { 411 return uuidA.length == 0; 412 } 413 414 HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid>(Arrays.asList(uuidA)); 415 for (ParcelUuid uuid : uuidB) { 416 if (uuidSet.contains(uuid)) return true; 417 } 418 return false; 419 } 420 421 /** 422 * Extract the Service Identifier or the actual uuid from the Parcel Uuid. For example, if 423 * 0000110B-0000-1000-8000-00805F9B34FB is the parcel Uuid, this function will return 110B 424 */ getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid)425 private static int getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid) { 426 UUID uuid = parcelUuid.getUuid(); 427 long value = (uuid.getMostSignificantBits() & 0xFFFFFFFF00000000L) >>> 32; 428 return (int) value; 429 } 430 431 /** 432 * Parse UUID from bytes. The {@code uuidBytes} can represent a 16-bit, 32-bit or 128-bit UUID, 433 * but the returned UUID is always in 128-bit format. Note UUID is little endian in Bluetooth. 434 * 435 * @param uuidBytes Byte representation of uuid. 436 * @return {@link ParcelUuid} parsed from bytes. 437 * @throws IllegalArgumentException If the {@code uuidBytes} cannot be parsed. 438 * @hide 439 */ 440 @NonNull 441 @SystemApi parseUuidFrom(@ullable byte[] uuidBytes)442 public static ParcelUuid parseUuidFrom(@Nullable byte[] uuidBytes) { 443 if (uuidBytes == null) { 444 throw new IllegalArgumentException("uuidBytes cannot be null"); 445 } 446 int length = uuidBytes.length; 447 if (length != UUID_BYTES_16_BIT 448 && length != UUID_BYTES_32_BIT 449 && length != UUID_BYTES_128_BIT) { 450 throw new IllegalArgumentException("uuidBytes length invalid - " + length); 451 } 452 453 // Construct a 128 bit UUID. 454 if (length == UUID_BYTES_128_BIT) { 455 ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN); 456 long msb = buf.getLong(8); 457 long lsb = buf.getLong(0); 458 return new ParcelUuid(new UUID(msb, lsb)); 459 } 460 461 // For 16 bit and 32 bit UUID we need to convert them to 128 bit value. 462 // 128_bit_value = uuid * 2^96 + BASE_UUID 463 long shortUuid; 464 if (length == UUID_BYTES_16_BIT) { 465 shortUuid = uuidBytes[0] & 0xFF; 466 shortUuid += (uuidBytes[1] & 0xFF) << 8; 467 } else { 468 shortUuid = uuidBytes[0] & 0xFF; 469 shortUuid += (uuidBytes[1] & 0xFF) << 8; 470 shortUuid += (uuidBytes[2] & 0xFF) << 16; 471 shortUuid += (uuidBytes[3] & 0xFF) << 24; 472 } 473 long msb = BASE_UUID.getUuid().getMostSignificantBits() + (shortUuid << 32); 474 long lsb = BASE_UUID.getUuid().getLeastSignificantBits(); 475 return new ParcelUuid(new UUID(msb, lsb)); 476 } 477 478 /** 479 * Parse UUID to bytes. The returned value is shortest representation, a 16-bit, 32-bit or 480 * 128-bit UUID, Note returned value is little endian (Bluetooth). 481 * 482 * @param uuid uuid to parse. 483 * @return shortest representation of {@code uuid} as bytes. 484 * @throws IllegalArgumentException If the {@code uuid} is null. 485 * @hide 486 */ uuidToBytes(ParcelUuid uuid)487 public static byte[] uuidToBytes(ParcelUuid uuid) { 488 if (uuid == null) { 489 throw new IllegalArgumentException("uuid cannot be null"); 490 } 491 492 if (is16BitUuid(uuid)) { 493 byte[] uuidBytes = new byte[UUID_BYTES_16_BIT]; 494 int uuidVal = getServiceIdentifierFromParcelUuid(uuid); 495 uuidBytes[0] = (byte) (uuidVal & 0xFF); 496 uuidBytes[1] = (byte) ((uuidVal & 0xFF00) >> 8); 497 return uuidBytes; 498 } 499 500 if (is32BitUuid(uuid)) { 501 byte[] uuidBytes = new byte[UUID_BYTES_32_BIT]; 502 int uuidVal = getServiceIdentifierFromParcelUuid(uuid); 503 uuidBytes[0] = (byte) (uuidVal & 0xFF); 504 uuidBytes[1] = (byte) ((uuidVal & 0xFF00) >> 8); 505 uuidBytes[2] = (byte) ((uuidVal & 0xFF0000) >> 16); 506 uuidBytes[3] = (byte) ((uuidVal & 0xFF000000) >> 24); 507 return uuidBytes; 508 } 509 510 // Construct a 128 bit UUID. 511 long msb = uuid.getUuid().getMostSignificantBits(); 512 long lsb = uuid.getUuid().getLeastSignificantBits(); 513 514 byte[] uuidBytes = new byte[UUID_BYTES_128_BIT]; 515 ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN); 516 buf.putLong(8, msb); 517 buf.putLong(0, lsb); 518 return uuidBytes; 519 } 520 521 /** 522 * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid. 523 * 524 * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise. 525 * @hide 526 */ 527 @UnsupportedAppUsage is16BitUuid(ParcelUuid parcelUuid)528 public static boolean is16BitUuid(ParcelUuid parcelUuid) { 529 UUID uuid = parcelUuid.getUuid(); 530 if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { 531 return false; 532 } 533 return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L); 534 } 535 536 /** 537 * Check whether the given parcelUuid can be converted to 32 bit bluetooth uuid. 538 * 539 * @return true if the parcelUuid can be converted to 32 bit uuid, false otherwise. 540 * @hide 541 */ 542 @UnsupportedAppUsage is32BitUuid(ParcelUuid parcelUuid)543 public static boolean is32BitUuid(ParcelUuid parcelUuid) { 544 UUID uuid = parcelUuid.getUuid(); 545 if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { 546 return false; 547 } 548 if (is16BitUuid(parcelUuid)) { 549 return false; 550 } 551 return ((uuid.getMostSignificantBits() & 0xFFFFFFFFL) == 0x1000L); 552 } 553 BluetoothUuid()554 private BluetoothUuid() {} 555 } 556