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