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