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