1 /**
2  * Copyright (C) 2016 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 static java.util.Objects.requireNonNull;
20 
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.SystemApi;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 
31 /**
32  * Out Of Band Data for Bluetooth device pairing.
33  *
34  * <p>This object represents optional data obtained from a remote device through
35  * an out-of-band channel (eg. NFC, QR).
36  *
37  * <p>References:
38  * NFC AD Forum SSP 1.1 (AD)
39  * {@link https://members.nfc-forum.org//apps/group_public/download.php/24620/NFCForum-AD-BTSSP_1_1.pdf}
40  * Core Specification Supplement (CSS) V9
41  *
42  * <p>There are several BR/EDR Examples
43  *
44  * <p>Negotiated Handover:
45  *   Bluetooth Carrier Configuration Record:
46  *    - OOB Data Length
47  *    - Device Address
48  *    - Class of Device
49  *    - Simple Pairing Hash C
50  *    - Simple Pairing Randomizer R
51  *    - Service Class UUID
52  *    - Bluetooth Local Name
53  *
54  * <p>Static Handover:
55  *   Bluetooth Carrier Configuration Record:
56  *    - OOB Data Length
57  *    - Device Address
58  *    - Class of Device
59  *    - Service Class UUID
60  *    - Bluetooth Local Name
61  *
62  * <p>Simplified Tag Format for Single BT Carrier:
63  *   Bluetooth OOB Data Record:
64  *    - OOB Data Length
65  *    - Device Address
66  *    - Class of Device
67  *    - Service Class UUID
68  *    - Bluetooth Local Name
69  *
70  * @hide
71  */
72 @SystemApi
73 public final class OobData implements Parcelable {
74 
75     private static final String TAG = "OobData";
76     /** The {@link OobData#mClassicLength} may be. (AD 3.1.1) (CSS 1.6.2) @hide */
77     @SystemApi
78     public static final int OOB_LENGTH_OCTETS = 2;
79     /**
80      * The length for the {@link OobData#mDeviceAddressWithType}(6) and Address Type(1).
81      * (AD 3.1.2) (CSS 1.6.2)
82      * @hide
83      */
84     @SystemApi
85     public static final int DEVICE_ADDRESS_OCTETS = 7;
86     /** The Class of Device is 3 octets. (AD 3.1.3) (CSS 1.6.2) @hide */
87     @SystemApi
88     public static final int CLASS_OF_DEVICE_OCTETS = 3;
89     /** The Confirmation data must be 16 octets. (AD 3.2.2) (CSS 1.6.2) @hide */
90     @SystemApi
91     public static final int CONFIRMATION_OCTETS = 16;
92     /** The Randomizer data must be 16 octets. (AD 3.2.3) (CSS 1.6.2) @hide */
93     @SystemApi
94     public static final int RANDOMIZER_OCTETS = 16;
95     /** The LE Device Role length is 1 octet. (AD 3.3.2) (CSS 1.17) @hide */
96     @SystemApi
97     public static final int LE_DEVICE_ROLE_OCTETS = 1;
98     /** The {@link OobData#mLeTemporaryKey} length. (3.4.1) @hide */
99     @SystemApi
100     public static final int LE_TK_OCTETS = 16;
101     /** The {@link OobData#mLeAppearance} length. (3.4.1) @hide */
102     @SystemApi
103     public static final int LE_APPEARANCE_OCTETS = 2;
104     /** The {@link OobData#mLeFlags} length. (3.4.1) @hide */
105     @SystemApi
106     public static final int LE_DEVICE_FLAG_OCTETS = 1; // 1 octet to hold the 0-4 value.
107 
108     // Le Roles
109     /** @hide */
110     @Retention(RetentionPolicy.SOURCE)
111     @IntDef(
112         prefix = { "LE_DEVICE_ROLE_" },
113         value = {
114             LE_DEVICE_ROLE_PERIPHERAL_ONLY,
115             LE_DEVICE_ROLE_CENTRAL_ONLY,
116             LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL,
117             LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL
118         }
119     )
120     public @interface LeRole {}
121 
122     /** @hide */
123     @SystemApi
124     public static final int LE_DEVICE_ROLE_PERIPHERAL_ONLY = 0x00;
125     /** @hide */
126     @SystemApi
127     public static final int LE_DEVICE_ROLE_CENTRAL_ONLY = 0x01;
128     /** @hide */
129     @SystemApi
130     public static final int LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL = 0x02;
131     /** @hide */
132     @SystemApi
133     public static final int LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL = 0x03;
134 
135     // Le Flags
136     /** @hide */
137     @Retention(RetentionPolicy.SOURCE)
138     @IntDef(
139         prefix = { "LE_FLAG_" },
140         value = {
141             LE_FLAG_LIMITED_DISCOVERY_MODE,
142             LE_FLAG_GENERAL_DISCOVERY_MODE,
143             LE_FLAG_BREDR_NOT_SUPPORTED,
144             LE_FLAG_SIMULTANEOUS_CONTROLLER,
145             LE_FLAG_SIMULTANEOUS_HOST
146         }
147     )
148     public @interface LeFlag {}
149 
150     /** @hide */
151     @SystemApi
152     public static final int LE_FLAG_LIMITED_DISCOVERY_MODE = 0x00;
153     /** @hide */
154     @SystemApi
155     public static final int LE_FLAG_GENERAL_DISCOVERY_MODE = 0x01;
156     /** @hide */
157     @SystemApi
158     public static final int LE_FLAG_BREDR_NOT_SUPPORTED = 0x02;
159     /** @hide */
160     @SystemApi
161     public static final int LE_FLAG_SIMULTANEOUS_CONTROLLER = 0x03;
162     /** @hide */
163     @SystemApi
164     public static final int LE_FLAG_SIMULTANEOUS_HOST = 0x04;
165 
166     /**
167      * Builds an {@link OobData} object and validates that the required combination
168      * of values are present to create the LE specific OobData type.
169      *
170      * @hide
171      */
172     @SystemApi
173     public static final class LeBuilder {
174 
175         /**
176          * It is recommended that this Hash C is generated anew for each
177          * pairing.
178          *
179          * <p>It should be noted that on passive NFC this isn't possible as the data is static
180          * and immutable.
181          */
182         private byte[] mConfirmationHash = null;
183 
184         /**
185          * Optional, but adds more validity to the pairing.
186          *
187          * <p>If not present a value of 0 is assumed.
188          */
189         private byte[] mRandomizerHash = new byte[] {
190             0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
191             0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
192         };
193 
194         /**
195          * The Bluetooth Device user-friendly name presented over Bluetooth Technology.
196          *
197          * <p>This is the name that may be displayed to the device user as part of the UI.
198          */
199         private byte[] mDeviceName = null;
200 
201         /**
202          * Sets the Bluetooth Device name to be used for UI purposes.
203          *
204          * <p>Optional attribute.
205          *
206          * @param deviceName byte array representing the name, may be 0 in length, not null.
207          *
208          * @return {@link OobData#ClassicBuilder}
209          *
210          * @throws NullPointerException if deviceName is null.
211          *
212          * @hide
213          */
214         @NonNull
215         @SystemApi
setDeviceName(@onNull byte[] deviceName)216         public LeBuilder setDeviceName(@NonNull byte[] deviceName) {
217             requireNonNull(deviceName);
218             this.mDeviceName = deviceName;
219             return this;
220         }
221 
222         /**
223          * The Bluetooth Device Address is the address to which the OOB data belongs.
224          *
225          * <p>The length MUST be {@link OobData#DEVICE_ADDRESS_OCTETS} octets.
226          *
227          * <p> Address is encoded in Little Endian order.
228          *
229          * <p>e.g. 00:01:02:03:04:05 would be x05x04x03x02x01x00
230          */
231         private final byte[] mDeviceAddressWithType;
232 
233         /**
234          * During an LE connection establishment, one must be in the Peripheral mode and the other
235          * in the Central role.
236          *
237          * <p>Possible Values:
238          * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
239          * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
240          * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
241          * Peripheral Preferred
242          * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
243          * 0x04 - 0xFF Reserved
244          */
245         private final @LeRole int mLeDeviceRole;
246 
247         /**
248          * Temporary key value from the Security Manager.
249          *
250          * <p> Must be {@link LE_TK_OCTETS} in size
251          */
252         private byte[] mLeTemporaryKey = null;
253 
254         /**
255          * Defines the representation of the external appearance of the device.
256          *
257          * <p>For example, a mouse, remote control, or keyboard.
258          *
259          * <p>Used for visual on discovering device to represent icon/string/etc...
260          */
261         private byte[] mLeAppearance = null;
262 
263         /**
264          * Contains which discoverable mode to use, BR/EDR support and capability.
265          *
266          * <p>Possible LE Flags:
267          * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
268          * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
269          * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
270          * LMP Feature Mask Definitions.
271          * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
272          * Same Device Capable (Controller).
273          * Bit 49 of LMP Feature Mask Definitions.
274          * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
275          * Same Device Capable (Host).
276          * Bit 55 of LMP Feature Mask Definitions.
277          * <b>0x05- 0x07 Reserved</b>
278          */
279         private @LeFlag int mLeFlags = LE_FLAG_GENERAL_DISCOVERY_MODE; // Invalid default
280 
281         /**
282          * Main creation method for creating a LE version of {@link OobData}.
283          *
284          * <p>This object will allow the caller to call {@link LeBuilder#build()}
285          * to build the data object or add any option information to the builder.
286          *
287          * @param deviceAddressWithType the LE device address plus the address type (7 octets);
288          * not null.
289          * @param leDeviceRole whether the device supports Peripheral, Central,
290          * Both including preference; not null. (1 octet)
291          * @param confirmationHash Array consisting of {@link OobData#CONFIRMATION_OCTETS} octets
292          * of data. Data is derived from controller/host stack and is
293          * required for pairing OOB.
294          *
295          * <p>Possible Values:
296          * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
297          * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
298          * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
299          * Peripheral Preferred
300          * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
301          * 0x04 - 0xFF Reserved
302          *
303          * @throws IllegalArgumentException if any of the values fail to be set.
304          * @throws NullPointerException if any argument is null.
305          *
306          * @hide
307          */
308         @SystemApi
LeBuilder(@onNull byte[] confirmationHash, @NonNull byte[] deviceAddressWithType, @LeRole int leDeviceRole)309         public LeBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] deviceAddressWithType,
310                 @LeRole int leDeviceRole) {
311             requireNonNull(confirmationHash);
312             requireNonNull(deviceAddressWithType);
313             if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
314                 throw new IllegalArgumentException("confirmationHash must be "
315                     + OobData.CONFIRMATION_OCTETS + " octets in length.");
316             }
317             this.mConfirmationHash = confirmationHash;
318             if (deviceAddressWithType.length != OobData.DEVICE_ADDRESS_OCTETS) {
319                 throw new IllegalArgumentException("confirmationHash must be "
320                     + OobData.DEVICE_ADDRESS_OCTETS+ " octets in length.");
321             }
322             this.mDeviceAddressWithType = deviceAddressWithType;
323             if (leDeviceRole < LE_DEVICE_ROLE_PERIPHERAL_ONLY
324                     || leDeviceRole > LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL) {
325                 throw new IllegalArgumentException("leDeviceRole must be a valid value.");
326             }
327             this.mLeDeviceRole = leDeviceRole;
328         }
329 
330         /**
331          * Sets the Temporary Key value to be used by the LE Security Manager during
332          * LE pairing.
333          *
334          * @param leTemporaryKey byte array that shall be 16 bytes. Please see Bluetooth CSSv6,
335          * Part A 1.8 for a detailed description.
336          *
337          * @return {@link OobData#Builder}
338          *
339          * @throws IllegalArgumentException if the leTemporaryKey is an invalid format.
340          * @throws NullinterException if leTemporaryKey is null.
341          *
342          * @hide
343          */
344         @NonNull
345         @SystemApi
setLeTemporaryKey(@onNull byte[] leTemporaryKey)346         public LeBuilder setLeTemporaryKey(@NonNull byte[] leTemporaryKey) {
347             requireNonNull(leTemporaryKey);
348             if (leTemporaryKey.length != LE_TK_OCTETS) {
349                 throw new IllegalArgumentException("leTemporaryKey must be "
350                         + LE_TK_OCTETS + " octets in length.");
351             }
352             this.mLeTemporaryKey = leTemporaryKey;
353             return this;
354         }
355 
356         /**
357          * @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets
358          * of data. Data is derived from controller/host stack and is required for pairing OOB.
359          * Also, randomizerHash may be all 0s or null in which case it becomes all 0s.
360          *
361          * @throws IllegalArgumentException if null or incorrect length randomizerHash was passed.
362          * @throws NullPointerException if randomizerHash is null.
363          *
364          * @hide
365          */
366         @NonNull
367         @SystemApi
setRandomizerHash(@onNull byte[] randomizerHash)368         public LeBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
369             requireNonNull(randomizerHash);
370             if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
371                 throw new IllegalArgumentException("randomizerHash must be "
372                     + OobData.RANDOMIZER_OCTETS + " octets in length.");
373             }
374             this.mRandomizerHash = randomizerHash;
375             return this;
376         }
377 
378         /**
379          * Sets the LE Flags necessary for the pairing scenario or discovery mode.
380          *
381          * @param leFlags enum value representing the 1 octet of data about discovery modes.
382          *
383          * <p>Possible LE Flags:
384          * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
385          * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
386          * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
387          * LMP Feature Mask Definitions.
388          * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
389          * Same Device Capable (Controller) Bit 49 of LMP Feature Mask Definitions.
390          * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
391          * Same Device Capable (Host).
392          * Bit 55 of LMP Feature Mask Definitions.
393          * 0x05- 0x07 Reserved
394          *
395          * @throws IllegalArgumentException for invalid flag
396          * @hide
397          */
398         @NonNull
399         @SystemApi
setLeFlags(@eFlag int leFlags)400         public LeBuilder setLeFlags(@LeFlag int leFlags) {
401             if (leFlags < LE_FLAG_LIMITED_DISCOVERY_MODE || leFlags > LE_FLAG_SIMULTANEOUS_HOST) {
402                 throw new IllegalArgumentException("leFlags must be a valid value.");
403             }
404             this.mLeFlags = leFlags;
405             return this;
406         }
407 
408         /**
409          * Validates and builds the {@link OobData} object for LE Security.
410          *
411          * @return {@link OobData} with given builder values
412          *
413          * @throws IllegalStateException if either of the 2 required fields were not set.
414          *
415          * @hide
416          */
417         @NonNull
418         @SystemApi
build()419         public OobData build() {
420             final OobData oob =
421                     new OobData(this.mDeviceAddressWithType, this.mLeDeviceRole,
422                             this.mConfirmationHash);
423 
424             // If we have values, set them, otherwise use default
425             oob.mLeTemporaryKey =
426                     (this.mLeTemporaryKey != null) ? this.mLeTemporaryKey : oob.mLeTemporaryKey;
427             oob.mLeAppearance = (this.mLeAppearance != null)
428                     ? this.mLeAppearance : oob.mLeAppearance;
429             oob.mLeFlags = (this.mLeFlags != 0xF) ? this.mLeFlags : oob.mLeFlags;
430             oob.mDeviceName = (this.mDeviceName != null) ? this.mDeviceName : oob.mDeviceName;
431             oob.mRandomizerHash = this.mRandomizerHash;
432             return oob;
433         }
434     }
435 
436     /**
437      * Builds an {@link OobData} object and validates that the required combination
438      * of values are present to create the Classic specific OobData type.
439      *
440      * @hide
441      */
442     @SystemApi
443     public static final class ClassicBuilder {
444         // Used by both Classic and LE
445         /**
446          * It is recommended that this Hash C is generated anew for each
447          * pairing.
448          *
449          * <p>It should be noted that on passive NFC this isn't possible as the data is static
450          * and immutable.
451          *
452          * @hide
453          */
454         private byte[] mConfirmationHash = null;
455 
456         /**
457          * Optional, but adds more validity to the pairing.
458          *
459          * <p>If not present a value of 0 is assumed.
460          *
461          * @hide
462          */
463         private byte[] mRandomizerHash = new byte[] {
464             0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
465             0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
466         };
467 
468         /**
469          * The Bluetooth Device user-friendly name presented over Bluetooth Technology.
470          *
471          * <p>This is the name that may be displayed to the device user as part of the UI.
472          *
473          * @hide
474          */
475         private byte[] mDeviceName = null;
476 
477         /**
478          * This length value provides the absolute length of total OOB data block used for
479          * Bluetooth BR/EDR
480          *
481          * <p>OOB communication, which includes the length field itself and the Bluetooth
482          * Device Address.
483          *
484          * <p>The minimum length that may be represented in this field is 8.
485          *
486          * @hide
487          */
488         private final byte[] mClassicLength;
489 
490         /**
491          * The Bluetooth Device Address is the address to which the OOB data belongs.
492          *
493          * <p>The length MUST be {@link OobData#DEVICE_ADDRESS_OCTETS} octets.
494          *
495          * <p> Address is encoded in Little Endian order.
496          *
497          * <p>e.g. 00:01:02:03:04:05 would be x05x04x03x02x01x00
498          *
499          * @hide
500          */
501         private final byte[] mDeviceAddressWithType;
502 
503         /**
504          * Class of Device information is to be used to provide a graphical representation
505          * to the user as part of UI involving operations.
506          *
507          * <p>This is not to be used to determine a particular service can be used.
508          *
509          * <p>The length MUST be {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
510          *
511          * @hide
512          */
513         private byte[] mClassOfDevice = null;
514 
515         /**
516          * Main creation method for creating a Classic version of {@link OobData}.
517          *
518          * <p>This object will allow the caller to call {@link ClassicBuilder#build()}
519          * to build the data object or add any option information to the builder.
520          *
521          * @param confirmationHash byte array consisting of {@link OobData#CONFIRMATION_OCTETS}
522          * octets of data. Data is derived from controller/host stack and is required for pairing
523          * OOB.
524          * @param classicLength byte array representing the length of data from 8-65535 across 2
525          * octets (0xXXXX).
526          * @param deviceAddressWithType byte array representing the Bluetooth Address of the device
527          * that owns the OOB data. (i.e. the originator) [6 octets]
528          *
529          * @throws IllegalArgumentException if any of the values fail to be set.
530          * @throws NullPointerException if any argument is null.
531          *
532          * @hide
533          */
534         @SystemApi
ClassicBuilder(@onNull byte[] confirmationHash, @NonNull byte[] classicLength, @NonNull byte[] deviceAddressWithType)535         public ClassicBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] classicLength,
536                 @NonNull byte[] deviceAddressWithType) {
537             requireNonNull(confirmationHash);
538             requireNonNull(classicLength);
539             requireNonNull(deviceAddressWithType);
540             if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
541                 throw new IllegalArgumentException("confirmationHash must be "
542                     + OobData.CONFIRMATION_OCTETS + " octets in length.");
543             }
544             this.mConfirmationHash = confirmationHash;
545             if (classicLength.length != OOB_LENGTH_OCTETS) {
546                 throw new IllegalArgumentException("classicLength must be "
547                         + OOB_LENGTH_OCTETS + " octets in length.");
548             }
549             this.mClassicLength = classicLength;
550             if (deviceAddressWithType.length != DEVICE_ADDRESS_OCTETS) {
551                 throw new IllegalArgumentException("deviceAddressWithType must be "
552                         + DEVICE_ADDRESS_OCTETS + " octets in length.");
553             }
554             this.mDeviceAddressWithType = deviceAddressWithType;
555         }
556 
557         /**
558          * @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets
559          * of data. Data is derived from controller/host stack and is required for pairing OOB.
560          * Also, randomizerHash may be all 0s or null in which case it becomes all 0s.
561          *
562          * @throws IllegalArgumentException if null or incorrect length randomizerHash was passed.
563          * @throws NullPointerException if randomizerHash is null.
564          *
565          * @hide
566          */
567         @NonNull
568         @SystemApi
setRandomizerHash(@onNull byte[] randomizerHash)569         public ClassicBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
570             requireNonNull(randomizerHash);
571             if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
572                 throw new IllegalArgumentException("randomizerHash must be "
573                     + OobData.RANDOMIZER_OCTETS + " octets in length.");
574             }
575             this.mRandomizerHash = randomizerHash;
576             return this;
577         }
578 
579         /**
580          * Sets the Bluetooth Device name to be used for UI purposes.
581          *
582          * <p>Optional attribute.
583          *
584          * @param deviceName byte array representing the name, may be 0 in length, not null.
585          *
586          * @return {@link OobData#ClassicBuilder}
587          *
588          * @throws NullPointerException if deviceName is null
589          *
590          * @hide
591          */
592         @NonNull
593         @SystemApi
setDeviceName(@onNull byte[] deviceName)594         public ClassicBuilder setDeviceName(@NonNull byte[] deviceName) {
595             requireNonNull(deviceName);
596             this.mDeviceName = deviceName;
597             return this;
598         }
599 
600         /**
601          * Sets the Bluetooth Class of Device; used for UI purposes only.
602          *
603          * <p>Not an indicator of available services!
604          *
605          * <p>Optional attribute.
606          *
607          * @param classOfDevice byte array of {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
608          *
609          * @return {@link OobData#ClassicBuilder}
610          *
611          * @throws IllegalArgumentException if length is not equal to
612          * {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
613          * @throws NullPointerException if classOfDevice is null.
614          *
615          * @hide
616          */
617         @NonNull
618         @SystemApi
setClassOfDevice(@onNull byte[] classOfDevice)619         public ClassicBuilder setClassOfDevice(@NonNull byte[] classOfDevice) {
620             requireNonNull(classOfDevice);
621             if (classOfDevice.length != OobData.CLASS_OF_DEVICE_OCTETS) {
622                 throw new IllegalArgumentException("classOfDevice must be "
623                         + OobData.CLASS_OF_DEVICE_OCTETS + " octets in length.");
624             }
625             this.mClassOfDevice = classOfDevice;
626             return this;
627         }
628 
629         /**
630          * Validates and builds the {@link OobDat object for Classic Security.
631          *
632          * @return {@link OobData} with previously given builder values.
633          *
634          * @hide
635          */
636         @NonNull
637         @SystemApi
build()638         public OobData build() {
639             final OobData oob =
640                     new OobData(this.mClassicLength, this.mDeviceAddressWithType,
641                             this.mConfirmationHash);
642             // If we have values, set them, otherwise use default
643             oob.mDeviceName = (this.mDeviceName != null) ? this.mDeviceName : oob.mDeviceName;
644             oob.mClassOfDevice = (this.mClassOfDevice != null)
645                     ? this.mClassOfDevice : oob.mClassOfDevice;
646             oob.mRandomizerHash = this.mRandomizerHash;
647             return oob;
648         }
649     }
650 
651     // Members (Defaults for Optionals must be set or Parceling fails on NPE)
652     // Both
653     private final byte[] mDeviceAddressWithType;
654     private final byte[] mConfirmationHash;
655     private byte[] mRandomizerHash = new byte[] {
656         0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
657         0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
658     };
659     // Default the name to "Bluetooth Device"
660     private byte[] mDeviceName = new byte[] {
661         // Bluetooth
662         0x42, 0x6c, 0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68,
663         // <space>Device
664         0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65
665     };
666 
667     // Classic
668     private final byte[] mClassicLength;
669     private byte[] mClassOfDevice = new byte[CLASS_OF_DEVICE_OCTETS];
670 
671     // LE
672     private final @LeRole int mLeDeviceRole;
673     private byte[] mLeTemporaryKey = new byte[LE_TK_OCTETS];
674     private byte[] mLeAppearance = new byte[LE_APPEARANCE_OCTETS];
675     private @LeFlag int mLeFlags = LE_FLAG_LIMITED_DISCOVERY_MODE;
676 
677     /**
678      * @return byte array representing the MAC address of a bluetooth device.
679      * The Address is 6 octets long with a 1 octet address type associated with the address.
680      *
681      * <p>For classic this will be 6 byte address plus the default of PUBLIC_ADDRESS Address Type.
682      * For LE there are more choices for Address Type.
683      *
684      * @hide
685      */
686     @NonNull
687     @SystemApi
getDeviceAddressWithType()688     public byte[] getDeviceAddressWithType() {
689         return mDeviceAddressWithType;
690     }
691 
692     /**
693      * @return byte array representing the confirmationHash value
694      * which is used to confirm the identity to the controller.
695      *
696      * @hide
697      */
698     @NonNull
699     @SystemApi
getConfirmationHash()700     public byte[] getConfirmationHash() {
701         return mConfirmationHash;
702     }
703 
704     /**
705      * @return byte array representing the randomizerHash value
706      * which is used to verify the identity of the controller.
707      *
708      * @hide
709      */
710     @NonNull
711     @SystemApi
getRandomizerHash()712     public byte[] getRandomizerHash() {
713         return mRandomizerHash;
714     }
715 
716     /**
717      * @return Device Name used for displaying name in UI.
718      *
719      * <p>Also, this will be populated with the LE Local Name if the data is for LE.
720      *
721      * @hide
722      */
723     @Nullable
724     @SystemApi
getDeviceName()725     public byte[] getDeviceName() {
726         return mDeviceName;
727     }
728 
729     /**
730      * @return byte array representing the oob data length which is the length
731      * of all of the data including these octets.
732      *
733      * @hide
734      */
735     @NonNull
736     @SystemApi
getClassicLength()737     public byte[] getClassicLength() {
738         return mClassicLength;
739     }
740 
741     /**
742      * @return byte array representing the class of device for UI display.
743      *
744      * <p>Does not indicate services available; for display only.
745      *
746      * @hide
747      */
748     @NonNull
749     @SystemApi
getClassOfDevice()750     public byte[] getClassOfDevice() {
751         return mClassOfDevice;
752     }
753 
754     /**
755      * @return Temporary Key used for LE pairing.
756      *
757      * @hide
758      */
759     @Nullable
760     @SystemApi
getLeTemporaryKey()761     public byte[] getLeTemporaryKey() {
762         return mLeTemporaryKey;
763     }
764 
765     /**
766      * @return Appearance used for LE pairing. For use in UI situations
767      * when determining what sort of icons or text to display regarding
768      * the device.
769      *
770      * @hide
771      */
772     @Nullable
773     @SystemApi
getLeAppearance()774     public byte[] getLeAppearance() {
775         return mLeAppearance;
776     }
777 
778     /**
779      * @return Flags used to determing discoverable mode to use, BR/EDR Support, and Capability.
780      *
781      * <p>Possible LE Flags:
782      * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
783      * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
784      * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
785      * LMP Feature Mask Definitions.
786      * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
787      * Same Device Capable (Controller).
788      * Bit 49 of LMP Feature Mask Definitions.
789      * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
790      * Same Device Capable (Host).
791      * Bit 55 of LMP Feature Mask Definitions.
792      * <b>0x05- 0x07 Reserved</b>
793      *
794      * @hide
795      */
796     @NonNull
797     @SystemApi
798     @LeFlag
getLeFlags()799     public int getLeFlags() {
800         return mLeFlags;
801     }
802 
803     /**
804      * @return the supported and preferred roles of the LE device.
805      *
806      * <p>Possible Values:
807      * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
808      * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
809      * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
810      * Peripheral Preferred
811      * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
812      * 0x04 - 0xFF Reserved
813      *
814      * @hide
815      */
816     @NonNull
817     @SystemApi
818     @LeRole
getLeDeviceRole()819     public int getLeDeviceRole() {
820         return mLeDeviceRole;
821     }
822 
823     /**
824      * Classic Security Constructor
825      */
OobData(@onNull byte[] classicLength, @NonNull byte[] deviceAddressWithType, @NonNull byte[] confirmationHash)826     private OobData(@NonNull byte[] classicLength, @NonNull byte[] deviceAddressWithType,
827             @NonNull byte[] confirmationHash) {
828         mClassicLength = classicLength;
829         mDeviceAddressWithType = deviceAddressWithType;
830         mConfirmationHash = confirmationHash;
831         mLeDeviceRole = -1; // Satisfy final
832     }
833 
834     /**
835      * LE Security Constructor
836      */
OobData(@onNull byte[] deviceAddressWithType, @LeRole int leDeviceRole, @NonNull byte[] confirmationHash)837     private OobData(@NonNull byte[] deviceAddressWithType, @LeRole int leDeviceRole,
838             @NonNull byte[] confirmationHash) {
839         mDeviceAddressWithType = deviceAddressWithType;
840         mLeDeviceRole = leDeviceRole;
841         mConfirmationHash = confirmationHash;
842         mClassicLength = new byte[OOB_LENGTH_OCTETS]; // Satisfy final
843     }
844 
OobData(Parcel in)845     private OobData(Parcel in) {
846         // Both
847         mDeviceAddressWithType = in.createByteArray();
848         mConfirmationHash = in.createByteArray();
849         mRandomizerHash = in.createByteArray();
850         mDeviceName = in.createByteArray();
851 
852         // Classic
853         mClassicLength = in.createByteArray();
854         mClassOfDevice = in.createByteArray();
855 
856         // LE
857         mLeDeviceRole = in.readInt();
858         mLeTemporaryKey = in.createByteArray();
859         mLeAppearance = in.createByteArray();
860         mLeFlags = in.readInt();
861     }
862 
863     /**
864      * @hide
865      */
866     @Override
describeContents()867     public int describeContents() {
868         return 0;
869     }
870 
871     /**
872      * @hide
873      */
874     @Override
writeToParcel(@onNull Parcel out, int flags)875     public void writeToParcel(@NonNull Parcel out, int flags) {
876         // Both
877         // Required
878         out.writeByteArray(mDeviceAddressWithType);
879         // Required
880         out.writeByteArray(mConfirmationHash);
881         // Optional
882         out.writeByteArray(mRandomizerHash);
883         // Optional
884         out.writeByteArray(mDeviceName);
885 
886         // Classic
887         // Required
888         out.writeByteArray(mClassicLength);
889         // Optional
890         out.writeByteArray(mClassOfDevice);
891 
892         // LE
893         // Required
894         out.writeInt(mLeDeviceRole);
895         // Required
896         out.writeByteArray(mLeTemporaryKey);
897         // Optional
898         out.writeByteArray(mLeAppearance);
899         // Optional
900         out.writeInt(mLeFlags);
901     }
902 
903     // For Parcelable
904     public static final @android.annotation.NonNull Parcelable.Creator<OobData> CREATOR =
905             new Parcelable.Creator<OobData>() {
906         public OobData createFromParcel(Parcel in) {
907             return new OobData(in);
908         }
909 
910         public OobData[] newArray(int size) {
911             return new OobData[size];
912         }
913     };
914 
915     /**
916      * @return a {@link String} representation of the OobData object.
917      *
918      * @hide
919      */
920     @Override
921     @NonNull
toString()922     public String toString() {
923         return "OobData: \n\t"
924             // Both
925             + "Device Address With Type: " +  toHexString(mDeviceAddressWithType) + "\n\t"
926             + "Confirmation: " + toHexString(mConfirmationHash) + "\n\t"
927             + "Randomizer: " + toHexString(mRandomizerHash) + "\n\t"
928             + "Device Name: " + toHexString(mDeviceName) + "\n\t"
929             // Classic
930             + "OobData Length: " +  toHexString(mClassicLength) + "\n\t"
931             + "Class of Device: " +  toHexString(mClassOfDevice) + "\n\t"
932             // LE
933             + "LE Device Role: " + toHexString(mLeDeviceRole) + "\n\t"
934             + "LE Temporary Key: " + toHexString(mLeTemporaryKey) + "\n\t"
935             + "LE Appearance: " + toHexString(mLeAppearance) + "\n\t"
936             + "LE Flags: " + toHexString(mLeFlags) + "\n\t";
937     }
938 
939     @NonNull
toHexString(@onNull int b)940     private String toHexString(@NonNull int b) {
941         return toHexString(new byte[] {(byte) b});
942     }
943 
944     @NonNull
toHexString(@onNull byte b)945     private String toHexString(@NonNull byte b) {
946         return toHexString(new byte[] {b});
947     }
948 
949     @NonNull
toHexString(@onNull byte[] array)950     private String toHexString(@NonNull byte[] array) {
951         StringBuilder builder = new StringBuilder(array.length * 2);
952         for (byte b: array) {
953             builder.append(String.format("%02x", b));
954         }
955         return builder.toString();
956     }
957 }
958