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.SystemApi; 22 import android.compat.annotation.UnsupportedAppUsage; 23 import android.os.ParcelUuid; 24 25 import java.nio.ByteBuffer; 26 import java.nio.ByteOrder; 27 import java.util.Arrays; 28 import java.util.HashSet; 29 import java.util.UUID; 30 31 /** 32 * Static helper methods and constants to decode the ParcelUuid of remote devices. 33 * 34 * @hide 35 */ 36 @SystemApi 37 public final class BluetoothUuid { 38 39 /* See Bluetooth Assigned Numbers document - SDP section, to get the values of UUIDs 40 * for the various services. 41 * 42 * The following 128 bit values are calculated as: 43 * uuid * 2^96 + BASE_UUID 44 */ 45 46 /** @hide */ 47 @NonNull 48 @SystemApi 49 public static final ParcelUuid A2DP_SINK = 50 ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"); 51 /** @hide */ 52 @NonNull 53 @SystemApi 54 public static final ParcelUuid A2DP_SOURCE = 55 ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB"); 56 /** @hide */ 57 @NonNull 58 @SystemApi 59 public static final ParcelUuid ADV_AUDIO_DIST = 60 ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB"); 61 /** @hide */ 62 @NonNull 63 @SystemApi 64 public static final ParcelUuid HSP = 65 ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB"); 66 /** @hide */ 67 @NonNull 68 @SystemApi 69 public static final ParcelUuid HSP_AG = 70 ParcelUuid.fromString("00001112-0000-1000-8000-00805F9B34FB"); 71 /** @hide */ 72 @NonNull 73 @SystemApi 74 public static final ParcelUuid HFP = 75 ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB"); 76 /** @hide */ 77 @NonNull 78 @SystemApi 79 public static final ParcelUuid HFP_AG = 80 ParcelUuid.fromString("0000111F-0000-1000-8000-00805F9B34FB"); 81 /** @hide */ 82 @NonNull 83 @SystemApi 84 public static final ParcelUuid AVRCP_CONTROLLER = 85 ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB"); 86 /** @hide */ 87 @NonNull 88 @SystemApi 89 public static final ParcelUuid AVRCP_TARGET = 90 ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB"); 91 /** @hide */ 92 @NonNull 93 @SystemApi 94 public static final ParcelUuid OBEX_OBJECT_PUSH = 95 ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb"); 96 /** @hide */ 97 @NonNull 98 @SystemApi 99 public static final ParcelUuid HID = 100 ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb"); 101 /** @hide */ 102 @NonNull 103 @SystemApi 104 public static final ParcelUuid HOGP = 105 ParcelUuid.fromString("00001812-0000-1000-8000-00805f9b34fb"); 106 /** @hide */ 107 @NonNull 108 @SystemApi 109 public static final ParcelUuid PANU = 110 ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB"); 111 /** @hide */ 112 @NonNull 113 @SystemApi 114 public static final ParcelUuid NAP = 115 ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB"); 116 /** @hide */ 117 @NonNull 118 @SystemApi 119 public static final ParcelUuid BNEP = 120 ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB"); 121 /** @hide */ 122 @NonNull 123 @SystemApi 124 public static final ParcelUuid PBAP_PCE = 125 ParcelUuid.fromString("0000112e-0000-1000-8000-00805F9B34FB"); 126 /** @hide */ 127 @NonNull 128 @SystemApi 129 public static final ParcelUuid PBAP_PSE = 130 ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB"); 131 /** @hide */ 132 @NonNull 133 @SystemApi 134 public static final ParcelUuid MAP = 135 ParcelUuid.fromString("00001134-0000-1000-8000-00805F9B34FB"); 136 /** @hide */ 137 @NonNull 138 @SystemApi 139 public static final ParcelUuid MNS = 140 ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB"); 141 /** @hide */ 142 @NonNull 143 @SystemApi 144 public static final ParcelUuid MAS = 145 ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB"); 146 /** @hide */ 147 @NonNull 148 @SystemApi 149 public static final ParcelUuid SAP = 150 ParcelUuid.fromString("0000112D-0000-1000-8000-00805F9B34FB"); 151 /** @hide */ 152 @NonNull 153 @SystemApi 154 public static final ParcelUuid HEARING_AID = 155 ParcelUuid.fromString("0000FDF0-0000-1000-8000-00805f9b34fb"); 156 157 /** @hide */ 158 @NonNull 159 @SystemApi 160 public static final ParcelUuid BASE_UUID = 161 ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); 162 163 /** 164 * Length of bytes for 16 bit UUID 165 * 166 * @hide 167 */ 168 @SystemApi 169 public static final int UUID_BYTES_16_BIT = 2; 170 /** 171 * Length of bytes for 32 bit UUID 172 * 173 * @hide 174 */ 175 @SystemApi 176 public static final int UUID_BYTES_32_BIT = 4; 177 /** 178 * Length of bytes for 128 bit UUID 179 * 180 * @hide 181 */ 182 @SystemApi 183 public static final int UUID_BYTES_128_BIT = 16; 184 185 /** 186 * Returns true if there any common ParcelUuids in uuidA and uuidB. 187 * 188 * @param uuidA - List of ParcelUuids 189 * @param uuidB - List of ParcelUuids 190 * 191 * @hide 192 */ 193 @SystemApi containsAnyUuid(@ullable ParcelUuid[] uuidA, @Nullable ParcelUuid[] uuidB)194 public static boolean containsAnyUuid(@Nullable ParcelUuid[] uuidA, 195 @Nullable ParcelUuid[] uuidB) { 196 if (uuidA == null && uuidB == null) return true; 197 198 if (uuidA == null) { 199 return uuidB.length == 0; 200 } 201 202 if (uuidB == null) { 203 return uuidA.length == 0; 204 } 205 206 HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid>(Arrays.asList(uuidA)); 207 for (ParcelUuid uuid : uuidB) { 208 if (uuidSet.contains(uuid)) return true; 209 } 210 return false; 211 } 212 213 /** 214 * Extract the Service Identifier or the actual uuid from the Parcel Uuid. 215 * For example, if 0000110B-0000-1000-8000-00805F9B34FB is the parcel Uuid, 216 * this function will return 110B 217 * 218 * @param parcelUuid 219 * @return the service identifier. 220 */ getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid)221 private static int getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid) { 222 UUID uuid = parcelUuid.getUuid(); 223 long value = (uuid.getMostSignificantBits() & 0xFFFFFFFF00000000L) >>> 32; 224 return (int) value; 225 } 226 227 /** 228 * Parse UUID from bytes. The {@code uuidBytes} can represent a 16-bit, 32-bit or 128-bit UUID, 229 * but the returned UUID is always in 128-bit format. 230 * Note UUID is little endian in Bluetooth. 231 * 232 * @param uuidBytes Byte representation of uuid. 233 * @return {@link ParcelUuid} parsed from bytes. 234 * @throws IllegalArgumentException If the {@code uuidBytes} cannot be parsed. 235 * 236 * @hide 237 */ 238 @NonNull 239 @SystemApi parseUuidFrom(@ullable byte[] uuidBytes)240 public static ParcelUuid parseUuidFrom(@Nullable byte[] uuidBytes) { 241 if (uuidBytes == null) { 242 throw new IllegalArgumentException("uuidBytes cannot be null"); 243 } 244 int length = uuidBytes.length; 245 if (length != UUID_BYTES_16_BIT && length != UUID_BYTES_32_BIT 246 && length != UUID_BYTES_128_BIT) { 247 throw new IllegalArgumentException("uuidBytes length invalid - " + length); 248 } 249 250 // Construct a 128 bit UUID. 251 if (length == UUID_BYTES_128_BIT) { 252 ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN); 253 long msb = buf.getLong(8); 254 long lsb = buf.getLong(0); 255 return new ParcelUuid(new UUID(msb, lsb)); 256 } 257 258 // For 16 bit and 32 bit UUID we need to convert them to 128 bit value. 259 // 128_bit_value = uuid * 2^96 + BASE_UUID 260 long shortUuid; 261 if (length == UUID_BYTES_16_BIT) { 262 shortUuid = uuidBytes[0] & 0xFF; 263 shortUuid += (uuidBytes[1] & 0xFF) << 8; 264 } else { 265 shortUuid = uuidBytes[0] & 0xFF; 266 shortUuid += (uuidBytes[1] & 0xFF) << 8; 267 shortUuid += (uuidBytes[2] & 0xFF) << 16; 268 shortUuid += (uuidBytes[3] & 0xFF) << 24; 269 } 270 long msb = BASE_UUID.getUuid().getMostSignificantBits() + (shortUuid << 32); 271 long lsb = BASE_UUID.getUuid().getLeastSignificantBits(); 272 return new ParcelUuid(new UUID(msb, lsb)); 273 } 274 275 /** 276 * Parse UUID to bytes. The returned value is shortest representation, a 16-bit, 32-bit or 277 * 128-bit UUID, Note returned value is little endian (Bluetooth). 278 * 279 * @param uuid uuid to parse. 280 * @return shortest representation of {@code uuid} as bytes. 281 * @throws IllegalArgumentException If the {@code uuid} is null. 282 * 283 * @hide 284 */ uuidToBytes(ParcelUuid uuid)285 public static byte[] uuidToBytes(ParcelUuid uuid) { 286 if (uuid == null) { 287 throw new IllegalArgumentException("uuid cannot be null"); 288 } 289 290 if (is16BitUuid(uuid)) { 291 byte[] uuidBytes = new byte[UUID_BYTES_16_BIT]; 292 int uuidVal = getServiceIdentifierFromParcelUuid(uuid); 293 uuidBytes[0] = (byte) (uuidVal & 0xFF); 294 uuidBytes[1] = (byte) ((uuidVal & 0xFF00) >> 8); 295 return uuidBytes; 296 } 297 298 if (is32BitUuid(uuid)) { 299 byte[] uuidBytes = new byte[UUID_BYTES_32_BIT]; 300 int uuidVal = getServiceIdentifierFromParcelUuid(uuid); 301 uuidBytes[0] = (byte) (uuidVal & 0xFF); 302 uuidBytes[1] = (byte) ((uuidVal & 0xFF00) >> 8); 303 uuidBytes[2] = (byte) ((uuidVal & 0xFF0000) >> 16); 304 uuidBytes[3] = (byte) ((uuidVal & 0xFF000000) >> 24); 305 return uuidBytes; 306 } 307 308 // Construct a 128 bit UUID. 309 long msb = uuid.getUuid().getMostSignificantBits(); 310 long lsb = uuid.getUuid().getLeastSignificantBits(); 311 312 byte[] uuidBytes = new byte[UUID_BYTES_128_BIT]; 313 ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN); 314 buf.putLong(8, msb); 315 buf.putLong(0, lsb); 316 return uuidBytes; 317 } 318 319 /** 320 * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid. 321 * 322 * @param parcelUuid 323 * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise. 324 * 325 * @hide 326 */ 327 @UnsupportedAppUsage is16BitUuid(ParcelUuid parcelUuid)328 public static boolean is16BitUuid(ParcelUuid parcelUuid) { 329 UUID uuid = parcelUuid.getUuid(); 330 if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { 331 return false; 332 } 333 return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L); 334 } 335 336 337 /** 338 * Check whether the given parcelUuid can be converted to 32 bit bluetooth uuid. 339 * 340 * @param parcelUuid 341 * @return true if the parcelUuid can be converted to 32 bit uuid, false otherwise. 342 * 343 * @hide 344 */ 345 @UnsupportedAppUsage is32BitUuid(ParcelUuid parcelUuid)346 public static boolean is32BitUuid(ParcelUuid parcelUuid) { 347 UUID uuid = parcelUuid.getUuid(); 348 if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) { 349 return false; 350 } 351 if (is16BitUuid(parcelUuid)) { 352 return false; 353 } 354 return ((uuid.getMostSignificantBits() & 0xFFFFFFFFL) == 0x1000L); 355 } 356 BluetoothUuid()357 private BluetoothUuid() {} 358 } 359