• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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