1 /* 2 * Copyright 2021 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 com.android.server.nearby.common.bluetooth.fastpair; 18 19 import static android.bluetooth.BluetoothProfile.A2DP; 20 import static android.bluetooth.BluetoothProfile.HEADSET; 21 22 import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothUuids.to128BitUuid; 23 import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothUuids.toFastPair128BitUuid; 24 25 import static com.google.common.primitives.Bytes.concat; 26 27 import android.bluetooth.BluetoothA2dp; 28 import android.bluetooth.BluetoothHeadset; 29 import android.util.Log; 30 31 import androidx.annotation.IntDef; 32 33 import com.android.server.nearby.common.bluetooth.BluetoothException; 34 import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattConnection; 35 36 import com.google.common.base.Preconditions; 37 import com.google.common.collect.ImmutableMap; 38 import com.google.common.primitives.Shorts; 39 40 import java.lang.annotation.Retention; 41 import java.lang.annotation.RetentionPolicy; 42 import java.nio.ByteBuffer; 43 import java.security.GeneralSecurityException; 44 import java.util.Random; 45 import java.util.UUID; 46 47 /** 48 * Fast Pair and Transport Discovery Service constants. 49 * 50 * <p>Unless otherwise specified, these numbers come from 51 * {https://www.bluetooth.com/specifications/gatt}. 52 */ 53 public final class Constants { 54 55 /** A2DP sink service uuid. */ 56 public static final short A2DP_SINK_SERVICE_UUID = 0x110B; 57 58 /** Headset service uuid. */ 59 public static final short HEADSET_SERVICE_UUID = 0x1108; 60 61 /** Hands free sink service uuid. */ 62 public static final short HANDS_FREE_SERVICE_UUID = 0x111E; 63 64 /** Bluetooth address length. */ 65 public static final int BLUETOOTH_ADDRESS_LENGTH = 6; 66 67 private static final String TAG = Constants.class.getSimpleName(); 68 69 /** 70 * Defined by https://developers.google.com/nearby/fast-pair/spec. 71 */ 72 public static final class FastPairService { 73 74 /** Fast Pair service UUID. */ 75 public static final UUID ID = to128BitUuid((short) 0xFE2C); 76 77 /** 78 * Characteristic to write verification bytes to during the key handshake. 79 */ 80 public static final class KeyBasedPairingCharacteristic { 81 82 private static final short SHORT_UUID = 0x1234; 83 84 /** 85 * Gets the new 128-bit UUID of this characteristic. 86 * 87 * <p>Note: For GATT server only. GATT client should use {@link 88 * KeyBasedPairingCharacteristic#getId(BluetoothGattConnection)}. 89 */ 90 public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID); 91 92 /** 93 * Gets the {@link UUID} of this characteristic. 94 * 95 * <p>This method is designed for being backward compatible with old version of UUID 96 * therefore needs the {@link BluetoothGattConnection} parameter to check the supported 97 * status of the Fast Pair provider. 98 */ getId(BluetoothGattConnection gattConnection)99 public static UUID getId(BluetoothGattConnection gattConnection) { 100 return getSupportedUuid(gattConnection, SHORT_UUID); 101 } 102 103 /** 104 * Constants related to the decrypted request written to this characteristic. 105 */ 106 public static final class Request { 107 108 /** 109 * The size of this message. 110 */ 111 public static final int SIZE = 16; 112 113 /** 114 * The index of this message for indicating the type byte. 115 */ 116 public static final int TYPE_INDEX = 0; 117 118 /** 119 * The index of this message for indicating the flags byte. 120 */ 121 public static final int FLAGS_INDEX = 1; 122 123 /** 124 * The index of this message for indicating the verification data start from. 125 */ 126 public static final int VERIFICATION_DATA_INDEX = 2; 127 128 /** 129 * The length of verification data, it is Provider’s current BLE address or public 130 * address. 131 */ 132 public static final int VERIFICATION_DATA_LENGTH = BLUETOOTH_ADDRESS_LENGTH; 133 134 /** 135 * The index of this message for indicating the seeker's public address start from. 136 */ 137 public static final int SEEKER_PUBLIC_ADDRESS_INDEX = 8; 138 139 /** 140 * The index of this message for indicating event group. 141 */ 142 public static final int EVENT_GROUP_INDEX = 8; 143 144 /** 145 * The index of this message for indicating event code. 146 */ 147 public static final int EVENT_CODE_INDEX = 9; 148 149 /** 150 * The index of this message for indicating the length of additional data of the 151 * event. 152 */ 153 public static final int EVENT_ADDITIONAL_DATA_LENGTH_INDEX = 10; 154 155 /** 156 * The index of this message for indicating the event additional data start from. 157 */ 158 public static final int EVENT_ADDITIONAL_DATA_INDEX = 11; 159 160 /** 161 * The index of this message for indicating the additional data type used in the 162 * following Additional Data characteristic. 163 */ 164 public static final int ADDITIONAL_DATA_TYPE_INDEX = 10; 165 166 /** 167 * The type of this message for Key-based Pairing Request. 168 */ 169 public static final byte TYPE_KEY_BASED_PAIRING_REQUEST = 0x00; 170 171 /** 172 * The bit indicating that the Fast Pair device should temporarily become 173 * discoverable. 174 */ 175 public static final byte REQUEST_DISCOVERABLE = (byte) (1 << 7); 176 177 /** 178 * The bit indicating that the requester (Seeker) has included their public address 179 * in bytes [7,12] of the request, and the Provider should initiate bonding to that 180 * address. 181 */ 182 public static final byte PROVIDER_INITIATES_BONDING = (byte) (1 << 6); 183 184 /** 185 * The bit indicating that Seeker requests Provider shall return the existing name. 186 */ 187 public static final byte REQUEST_DEVICE_NAME = (byte) (1 << 5); 188 189 /** 190 * The bit to request retroactive pairing. 191 */ 192 public static final byte REQUEST_RETROACTIVE_PAIR = (byte) (1 << 4); 193 194 /** 195 * The type of this message for action over BLE. 196 */ 197 public static final byte TYPE_ACTION_OVER_BLE = 0x10; 198 Request()199 private Request() { 200 } 201 } 202 203 /** 204 * Enumerates all flags of key-based pairing request. 205 */ 206 @Retention(RetentionPolicy.SOURCE) 207 @IntDef( 208 value = { 209 KeyBasedPairingRequestFlag.REQUEST_DISCOVERABLE, 210 KeyBasedPairingRequestFlag.PROVIDER_INITIATES_BONDING, 211 KeyBasedPairingRequestFlag.REQUEST_DEVICE_NAME, 212 KeyBasedPairingRequestFlag.REQUEST_RETROACTIVE_PAIR, 213 }) 214 public @interface KeyBasedPairingRequestFlag { 215 /** 216 * The bit indicating that the Fast Pair device should temporarily become 217 * discoverable. 218 */ 219 int REQUEST_DISCOVERABLE = (byte) (1 << 7); 220 /** 221 * The bit indicating that the requester (Seeker) has included their public address 222 * in bytes [7,12] of the request, and the Provider should initiate bonding to that 223 * address. 224 */ 225 int PROVIDER_INITIATES_BONDING = (byte) (1 << 6); 226 /** 227 * The bit indicating that Seeker requests Provider shall return the existing name. 228 */ 229 int REQUEST_DEVICE_NAME = (byte) (1 << 5); 230 /** 231 * The bit indicating that the Seeker request retroactive pairing. 232 */ 233 int REQUEST_RETROACTIVE_PAIR = (byte) (1 << 4); 234 } 235 236 /** 237 * Enumerates all flags of action over BLE request, see Fast Pair spec for details. 238 */ 239 @IntDef( 240 value = { 241 ActionOverBleFlag.DEVICE_ACTION, 242 ActionOverBleFlag.ADDITIONAL_DATA_CHARACTERISTIC, 243 }) 244 public @interface ActionOverBleFlag { 245 /** 246 * The bit indicating that the handshaking is for Device Action. 247 */ 248 int DEVICE_ACTION = (byte) (1 << 7); 249 /** 250 * The bit indicating that this handshake will be followed by Additional Data 251 * characteristic. 252 */ 253 int ADDITIONAL_DATA_CHARACTERISTIC = (byte) (1 << 6); 254 } 255 256 257 /** 258 * Constants related to the decrypted response sent back in a notify. 259 */ 260 public static final class Response { 261 262 /** 263 * The type of this message = Key-based Pairing Response. 264 */ 265 public static final byte TYPE = 0x01; 266 Response()267 private Response() { 268 } 269 } 270 KeyBasedPairingCharacteristic()271 private KeyBasedPairingCharacteristic() { 272 } 273 } 274 275 /** 276 * Characteristic used during Key-based Pairing, to exchange the encrypted passkey. 277 */ 278 public static final class PasskeyCharacteristic { 279 280 private static final short SHORT_UUID = 0x1235; 281 282 /** 283 * Gets the new 128-bit UUID of this characteristic. 284 * 285 * <p>Note: For GATT server only. GATT client should use {@link 286 * PasskeyCharacteristic#getId(BluetoothGattConnection)}. 287 */ 288 public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID); 289 290 /** 291 * Gets the {@link UUID} of this characteristic. 292 * 293 * <p>This method is designed for being backward compatible with old version of UUID 294 * therefore 295 * needs the {@link BluetoothGattConnection} parameter to check the supported status of 296 * the Fast Pair provider. 297 */ getId(BluetoothGattConnection gattConnection)298 public static UUID getId(BluetoothGattConnection gattConnection) { 299 return getSupportedUuid(gattConnection, SHORT_UUID); 300 } 301 302 /** 303 * The type of the Passkey Block message. 304 */ 305 @IntDef( 306 value = { 307 Type.SEEKER, 308 Type.PROVIDER, 309 }) 310 public @interface Type { 311 /** 312 * Seeker's Passkey. 313 */ 314 int SEEKER = (byte) 0x02; 315 /** 316 * Provider's Passkey. 317 */ 318 int PROVIDER = (byte) 0x03; 319 } 320 321 /** 322 * Constructs the encrypted value to write to the characteristic. 323 */ encrypt(@ype int type, byte[] secret, int passkey)324 public static byte[] encrypt(@Type int type, byte[] secret, int passkey) 325 throws GeneralSecurityException { 326 Preconditions.checkArgument( 327 0 < passkey && passkey < /*2^24=*/ 16777216, 328 "Passkey %s must be positive and fit in 3 bytes", 329 passkey); 330 byte[] passkeyBytes = 331 new byte[]{(byte) (passkey >>> 16), (byte) (passkey >>> 8), (byte) passkey}; 332 byte[] salt = 333 new byte[AesEcbSingleBlockEncryption.AES_BLOCK_LENGTH - 1 334 - passkeyBytes.length]; 335 new Random().nextBytes(salt); 336 return AesEcbSingleBlockEncryption.encrypt( 337 secret, concat(new byte[]{(byte) type}, passkeyBytes, salt)); 338 } 339 340 /** 341 * Extracts the passkey from the encrypted characteristic value. 342 */ decrypt(@ype int type, byte[] secret, byte[] passkeyCharacteristicValue)343 public static int decrypt(@Type int type, byte[] secret, 344 byte[] passkeyCharacteristicValue) 345 throws GeneralSecurityException { 346 byte[] decrypted = AesEcbSingleBlockEncryption 347 .decrypt(secret, passkeyCharacteristicValue); 348 if (decrypted[0] != (byte) type) { 349 throw new GeneralSecurityException( 350 "Wrong Passkey Block type (expected " + type + ", got " 351 + decrypted[0] + ")"); 352 } 353 return ByteBuffer.allocate(4) 354 .put((byte) 0) 355 .put(decrypted, /*offset=*/ 1, /*length=*/ 3) 356 .getInt(0); 357 } 358 PasskeyCharacteristic()359 private PasskeyCharacteristic() { 360 } 361 } 362 363 /** 364 * Characteristic to write to during the key exchange. 365 */ 366 public static final class AccountKeyCharacteristic { 367 368 private static final short SHORT_UUID = 0x1236; 369 370 /** 371 * Gets the new 128-bit UUID of this characteristic. 372 * 373 * <p>Note: For GATT server only. GATT client should use {@link 374 * AccountKeyCharacteristic#getId(BluetoothGattConnection)}. 375 */ 376 public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID); 377 378 /** 379 * Gets the {@link UUID} of this characteristic. 380 * 381 * <p>This method is designed for being backward compatible with old version of UUID 382 * therefore 383 * needs the {@link BluetoothGattConnection} parameter to check the supported status of 384 * the Fast Pair provider. 385 */ getId(BluetoothGattConnection gattConnection)386 public static UUID getId(BluetoothGattConnection gattConnection) { 387 return getSupportedUuid(gattConnection, SHORT_UUID); 388 } 389 390 /** 391 * The type for this message, account key request. 392 */ 393 public static final byte TYPE = 0x04; 394 AccountKeyCharacteristic()395 private AccountKeyCharacteristic() { 396 } 397 } 398 399 /** 400 * Characteristic to write to and notify on for handling personalized name, see {@link 401 * NamingEncoder}. 402 */ 403 public static final class NameCharacteristic { 404 405 private static final short SHORT_UUID = 0x1237; 406 407 /** 408 * Gets the new 128-bit UUID of this characteristic. 409 * 410 * <p>Note: For GATT server only. GATT client should use {@link 411 * NameCharacteristic#getId(BluetoothGattConnection)}. 412 */ 413 public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID); 414 415 /** 416 * Gets the {@link UUID} of this characteristic. 417 * 418 * <p>This method is designed for being backward compatible with old version of UUID 419 * therefore 420 * needs the {@link BluetoothGattConnection} parameter to check the supported status of 421 * the Fast Pair provider. 422 */ getId(BluetoothGattConnection gattConnection)423 public static UUID getId(BluetoothGattConnection gattConnection) { 424 return getSupportedUuid(gattConnection, SHORT_UUID); 425 } 426 NameCharacteristic()427 private NameCharacteristic() { 428 } 429 } 430 431 /** 432 * Characteristic to write to and notify on for handling additional data, see 433 * https://developers.google.com/nearby/fast-pair/early-access/spec#AdditionalData 434 */ 435 public static final class AdditionalDataCharacteristic { 436 437 private static final short SHORT_UUID = 0x1237; 438 439 public static final int DATA_ID_INDEX = 0; 440 public static final int DATA_LENGTH_INDEX = 1; 441 public static final int DATA_START_INDEX = 2; 442 443 /** 444 * Gets the new 128-bit UUID of this characteristic. 445 * 446 * <p>Note: For GATT server only. GATT client should use {@link 447 * AdditionalDataCharacteristic#getId(BluetoothGattConnection)}. 448 */ 449 public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID); 450 451 /** 452 * Gets the {@link UUID} of this characteristic. 453 * 454 * <p>This method is designed for being backward compatible with old version of UUID 455 * therefore 456 * needs the {@link BluetoothGattConnection} parameter to check the supported status of 457 * the Fast Pair provider. 458 */ getId(BluetoothGattConnection gattConnection)459 public static UUID getId(BluetoothGattConnection gattConnection) { 460 return getSupportedUuid(gattConnection, SHORT_UUID); 461 } 462 463 /** 464 * Enumerates all types of additional data. 465 */ 466 @Retention(RetentionPolicy.SOURCE) 467 @IntDef( 468 value = { 469 AdditionalDataType.PERSONALIZED_NAME, 470 AdditionalDataType.UNKNOWN, 471 }) 472 public @interface AdditionalDataType { 473 /** 474 * The value indicating that the type is for personalized name. 475 */ 476 int PERSONALIZED_NAME = (byte) 0x01; 477 int UNKNOWN = (byte) 0x00; // and all others. 478 } 479 } 480 481 /** 482 * Characteristic to control the beaconing feature (FastPair+Eddystone). 483 */ 484 public static final class BeaconActionsCharacteristic { 485 486 private static final short SHORT_UUID = 0x1238; 487 488 /** 489 * Gets the new 128-bit UUID of this characteristic. 490 * 491 * <p>Note: For GATT server only. GATT client should use {@link 492 * BeaconActionsCharacteristic#getId(BluetoothGattConnection)}. 493 */ 494 public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID); 495 496 /** 497 * Gets the {@link UUID} of this characteristic. 498 * 499 * <p>This method is designed for being backward compatible with old version of UUID 500 * therefore 501 * needs the {@link BluetoothGattConnection} parameter to check the supported status of 502 * the Fast Pair provider. 503 */ getId(BluetoothGattConnection gattConnection)504 public static UUID getId(BluetoothGattConnection gattConnection) { 505 return getSupportedUuid(gattConnection, SHORT_UUID); 506 } 507 508 /** 509 * Enumerates all types of beacon actions. 510 */ 511 /** Fast Pair Bond State. */ 512 @Retention(RetentionPolicy.SOURCE) 513 @IntDef( 514 value = { 515 BeaconActionType.READ_BEACON_PARAMETERS, 516 BeaconActionType.READ_PROVISIONING_STATE, 517 BeaconActionType.SET_EPHEMERAL_IDENTITY_KEY, 518 BeaconActionType.CLEAR_EPHEMERAL_IDENTITY_KEY, 519 BeaconActionType.READ_EPHEMERAL_IDENTITY_KEY, 520 BeaconActionType.RING, 521 BeaconActionType.READ_RINGING_STATE, 522 BeaconActionType.UNKNOWN, 523 }) 524 public @interface BeaconActionType { 525 int READ_BEACON_PARAMETERS = (byte) 0x00; 526 int READ_PROVISIONING_STATE = (byte) 0x01; 527 int SET_EPHEMERAL_IDENTITY_KEY = (byte) 0x02; 528 int CLEAR_EPHEMERAL_IDENTITY_KEY = (byte) 0x03; 529 int READ_EPHEMERAL_IDENTITY_KEY = (byte) 0x04; 530 int RING = (byte) 0x05; 531 int READ_RINGING_STATE = (byte) 0x06; 532 int UNKNOWN = (byte) 0xFF; // and all others 533 } 534 535 /** Converts value to enum. */ valueOf(byte value)536 public static @BeaconActionType int valueOf(byte value) { 537 switch(value) { 538 case BeaconActionType.READ_BEACON_PARAMETERS: 539 case BeaconActionType.READ_PROVISIONING_STATE: 540 case BeaconActionType.SET_EPHEMERAL_IDENTITY_KEY: 541 case BeaconActionType.CLEAR_EPHEMERAL_IDENTITY_KEY: 542 case BeaconActionType.READ_EPHEMERAL_IDENTITY_KEY: 543 case BeaconActionType.RING: 544 case BeaconActionType.READ_RINGING_STATE: 545 case BeaconActionType.UNKNOWN: 546 return value; 547 default: 548 return BeaconActionType.UNKNOWN; 549 } 550 } 551 } 552 553 554 /** 555 * Characteristic to read for checking firmware version. 0X2A26 is assigned number from 556 * bluetooth SIG website. 557 */ 558 public static final class FirmwareVersionCharacteristic { 559 560 /** UUID for firmware version. */ 561 public static final UUID ID = to128BitUuid((short) 0x2A26); 562 FirmwareVersionCharacteristic()563 private FirmwareVersionCharacteristic() { 564 } 565 } 566 FastPairService()567 private FastPairService() { 568 } 569 } 570 571 /** 572 * Defined by the BR/EDR Handover Profile. Pre-release version here: 573 * {https://jfarfel.users.x20web.corp.google.com/Bluetooth%20Handover%20d09.pdf} 574 */ 575 public interface TransportDiscoveryService { 576 577 UUID ID = to128BitUuid((short) 0x1824); 578 579 byte BLUETOOTH_SIG_ORGANIZATION_ID = 0x01; 580 byte SERVICE_UUIDS_16_BIT_LIST_TYPE = 0x01; 581 byte SERVICE_UUIDS_32_BIT_LIST_TYPE = 0x02; 582 byte SERVICE_UUIDS_128_BIT_LIST_TYPE = 0x03; 583 584 /** 585 * Writing to this allows you to activate the BR/EDR transport. 586 */ 587 interface ControlPointCharacteristic { 588 589 UUID ID = to128BitUuid((short) 0x2ABC); 590 byte ACTIVATE_TRANSPORT_OP_CODE = 0x01; 591 } 592 593 /** 594 * Info necessary to pair (mostly the Bluetooth Address). 595 */ 596 interface BrHandoverDataCharacteristic { 597 598 UUID ID = to128BitUuid((short) 0x2C01); 599 600 /** 601 * All bits are reserved for future use. 602 */ 603 byte BR_EDR_FEATURES = 0x00; 604 } 605 606 /** 607 * This characteristic exists only to wrap the descriptor. 608 */ 609 interface BluetoothSigDataCharacteristic { 610 611 UUID ID = to128BitUuid((short) 0x2C02); 612 613 /** 614 * The entire Transport Block data (e.g. supported Bluetooth services). 615 */ 616 interface BrTransportBlockDataDescriptor { 617 618 UUID ID = to128BitUuid((short) 0x2C03); 619 } 620 } 621 } 622 623 public static final UUID CLIENT_CHARACTERISTIC_CONFIGURATION_DESCRIPTOR_UUID = 624 to128BitUuid((short) 0x2902); 625 626 /** 627 * Wrapper for Bluetooth profile 628 */ 629 public static class Profile { 630 631 public final int type; 632 public final String name; 633 public final String connectionStateAction; 634 Profile(int type, String name, String connectionStateAction)635 private Profile(int type, String name, String connectionStateAction) { 636 this.type = type; 637 this.name = name; 638 this.connectionStateAction = connectionStateAction; 639 } 640 641 @Override toString()642 public String toString() { 643 return name; 644 } 645 } 646 647 /** 648 * {@link BluetoothHeadset} is used for both Headset and HandsFree (HFP). 649 */ 650 private static final Profile HEADSET_AND_HANDS_FREE_PROFILE = 651 new Profile( 652 HEADSET, "HEADSET_AND_HANDS_FREE", 653 BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); 654 655 /** Fast Pair supported profiles. */ 656 public static final ImmutableMap<Short, Profile> PROFILES = 657 ImmutableMap.<Short, Profile>builder() 658 .put( 659 Constants.A2DP_SINK_SERVICE_UUID, 660 new Profile(A2DP, "A2DP", 661 BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) 662 .put(Constants.HEADSET_SERVICE_UUID, HEADSET_AND_HANDS_FREE_PROFILE) 663 .put(Constants.HANDS_FREE_SERVICE_UUID, HEADSET_AND_HANDS_FREE_PROFILE) 664 .build(); 665 getSupportedProfiles()666 static short[] getSupportedProfiles() { 667 return Shorts.toArray(PROFILES.keySet()); 668 } 669 670 /** 671 * Helper method of getting 128-bit UUID for Fast Pair custom GATT characteristics. 672 * 673 * <p>This method is designed for being backward compatible with old version of UUID therefore 674 * needs the {@link BluetoothGattConnection} parameter to check the supported status of the Fast 675 * Pair provider. 676 * 677 * <p>Note: For new custom GATT characteristics, don't need to use this helper and please just 678 * call {@code toFastPair128BitUuid(shortUuid)} to get the UUID. Which also implies that callers 679 * don't need to provide {@link BluetoothGattConnection} to get the UUID anymore. 680 */ getSupportedUuid(BluetoothGattConnection gattConnection, short shortUuid)681 private static UUID getSupportedUuid(BluetoothGattConnection gattConnection, short shortUuid) { 682 // In worst case (new characteristic not found), this method's performance impact is about 683 // 6ms 684 // by using Pixel2 + JBL LIVE220. And the impact should be less and less along with more and 685 // more devices adopt the new characteristics. 686 try { 687 // Checks the new UUID first. 688 if (gattConnection 689 .getCharacteristic(FastPairService.ID, toFastPair128BitUuid(shortUuid)) 690 != null) { 691 Log.d(TAG, "Uses new KeyBasedPairingCharacteristic.ID"); 692 return toFastPair128BitUuid(shortUuid); 693 } 694 } catch (BluetoothException e) { 695 Log.d(TAG, "Uses old KeyBasedPairingCharacteristic.ID"); 696 } 697 // Returns the old UUID for default. 698 return to128BitUuid(shortUuid); 699 } 700 Constants()701 private Constants() { 702 } 703 } 704