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