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