blob: bb0b95649b179536c48220543f74f503acfed0b8 [file] [log] [blame]
/**
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.bluetooth;
import static java.util.Objects.requireNonNull;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Out Of Band Data for Bluetooth device pairing.
*
* <p>This object represents optional data obtained from a remote device through
* an out-of-band channel (eg. NFC, QR).
*
* <p>References:
* NFC AD Forum SSP 1.1 (AD)
* {@link https://members.nfc-forum.org//apps/group_public/download.php/24620/NFCForum-AD-BTSSP_1_1.pdf}
* Core Specification Supplement (CSS) V9
*
* <p>There are several BR/EDR Examples
*
* <p>Negotiated Handover:
* Bluetooth Carrier Configuration Record:
* - OOB Data Length
* - Device Address
* - Class of Device
* - Simple Pairing Hash C
* - Simple Pairing Randomizer R
* - Service Class UUID
* - Bluetooth Local Name
*
* <p>Static Handover:
* Bluetooth Carrier Configuration Record:
* - OOB Data Length
* - Device Address
* - Class of Device
* - Service Class UUID
* - Bluetooth Local Name
*
* <p>Simplified Tag Format for Single BT Carrier:
* Bluetooth OOB Data Record:
* - OOB Data Length
* - Device Address
* - Class of Device
* - Service Class UUID
* - Bluetooth Local Name
*
* @hide
*/
@SystemApi
public final class OobData implements Parcelable {
private static final String TAG = "OobData";
/** The {@link OobData#mClassicLength} may be. (AD 3.1.1) (CSS 1.6.2) @hide */
@SystemApi
public static final int OOB_LENGTH_OCTETS = 2;
/**
* The length for the {@link OobData#mDeviceAddressWithType}(6) and Address Type(1).
* (AD 3.1.2) (CSS 1.6.2)
* @hide
*/
@SystemApi
public static final int DEVICE_ADDRESS_OCTETS = 7;
/** The Class of Device is 3 octets. (AD 3.1.3) (CSS 1.6.2) @hide */
@SystemApi
public static final int CLASS_OF_DEVICE_OCTETS = 3;
/** The Confirmation data must be 16 octets. (AD 3.2.2) (CSS 1.6.2) @hide */
@SystemApi
public static final int CONFIRMATION_OCTETS = 16;
/** The Randomizer data must be 16 octets. (AD 3.2.3) (CSS 1.6.2) @hide */
@SystemApi
public static final int RANDOMIZER_OCTETS = 16;
/** The LE Device Role length is 1 octet. (AD 3.3.2) (CSS 1.17) @hide */
@SystemApi
public static final int LE_DEVICE_ROLE_OCTETS = 1;
/** The {@link OobData#mLeTemporaryKey} length. (3.4.1) @hide */
@SystemApi
public static final int LE_TK_OCTETS = 16;
/** The {@link OobData#mLeAppearance} length. (3.4.1) @hide */
@SystemApi
public static final int LE_APPEARANCE_OCTETS = 2;
/** The {@link OobData#mLeFlags} length. (3.4.1) @hide */
@SystemApi
public static final int LE_DEVICE_FLAG_OCTETS = 1; // 1 octet to hold the 0-4 value.
// Le Roles
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(
prefix = { "LE_DEVICE_ROLE_" },
value = {
LE_DEVICE_ROLE_PERIPHERAL_ONLY,
LE_DEVICE_ROLE_CENTRAL_ONLY,
LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL,
LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL
}
)
public @interface LeRole {}
/** @hide */
@SystemApi
public static final int LE_DEVICE_ROLE_PERIPHERAL_ONLY = 0x00;
/** @hide */
@SystemApi
public static final int LE_DEVICE_ROLE_CENTRAL_ONLY = 0x01;
/** @hide */
@SystemApi
public static final int LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL = 0x02;
/** @hide */
@SystemApi
public static final int LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL = 0x03;
// Le Flags
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(
prefix = { "LE_FLAG_" },
value = {
LE_FLAG_LIMITED_DISCOVERY_MODE,
LE_FLAG_GENERAL_DISCOVERY_MODE,
LE_FLAG_BREDR_NOT_SUPPORTED,
LE_FLAG_SIMULTANEOUS_CONTROLLER,
LE_FLAG_SIMULTANEOUS_HOST
}
)
public @interface LeFlag {}
/** @hide */
@SystemApi
public static final int LE_FLAG_LIMITED_DISCOVERY_MODE = 0x00;
/** @hide */
@SystemApi
public static final int LE_FLAG_GENERAL_DISCOVERY_MODE = 0x01;
/** @hide */
@SystemApi
public static final int LE_FLAG_BREDR_NOT_SUPPORTED = 0x02;
/** @hide */
@SystemApi
public static final int LE_FLAG_SIMULTANEOUS_CONTROLLER = 0x03;
/** @hide */
@SystemApi
public static final int LE_FLAG_SIMULTANEOUS_HOST = 0x04;
/**
* Builds an {@link OobData} object and validates that the required combination
* of values are present to create the LE specific OobData type.
*
* @hide
*/
@SystemApi
public static final class LeBuilder {
/**
* It is recommended that this Hash C is generated anew for each
* pairing.
*
* <p>It should be noted that on passive NFC this isn't possible as the data is static
* and immutable.
*/
private byte[] mConfirmationHash = null;
/**
* Optional, but adds more validity to the pairing.
*
* <p>If not present a value of 0 is assumed.
*/
private byte[] mRandomizerHash = new byte[] {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
/**
* The Bluetooth Device user-friendly name presented over Bluetooth Technology.
*
* <p>This is the name that may be displayed to the device user as part of the UI.
*/
private byte[] mDeviceName = null;
/**
* Sets the Bluetooth Device name to be used for UI purposes.
*
* <p>Optional attribute.
*
* @param deviceName byte array representing the name, may be 0 in length, not null.
*
* @return {@link OobData#ClassicBuilder}
*
* @throws NullPointerException if deviceName is null.
*
* @hide
*/
@NonNull
@SystemApi
public LeBuilder setDeviceName(@NonNull byte[] deviceName) {
requireNonNull(deviceName);
this.mDeviceName = deviceName;
return this;
}
/**
* The Bluetooth Device Address is the address to which the OOB data belongs.
*
* <p>The length MUST be {@link OobData#DEVICE_ADDRESS_OCTETS} octets.
*
* <p> Address is encoded in Little Endian order.
*
* <p>e.g. 00:01:02:03:04:05 would be x05x04x03x02x01x00
*/
private final byte[] mDeviceAddressWithType;
/**
* During an LE connection establishment, one must be in the Peripheral mode and the other
* in the Central role.
*
* <p>Possible Values:
* {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
* {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
* {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
* Peripheral Preferred
* {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
* 0x04 - 0xFF Reserved
*/
private final @LeRole int mLeDeviceRole;
/**
* Temporary key value from the Security Manager.
*
* <p> Must be {@link LE_TK_OCTETS} in size
*/
private byte[] mLeTemporaryKey = null;
/**
* Defines the representation of the external appearance of the device.
*
* <p>For example, a mouse, remote control, or keyboard.
*
* <p>Used for visual on discovering device to represent icon/string/etc...
*/
private byte[] mLeAppearance = null;
/**
* Contains which discoverable mode to use, BR/EDR support and capability.
*
* <p>Possible LE Flags:
* {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
* {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
* {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
* LMP Feature Mask Definitions.
* {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
* Same Device Capable (Controller).
* Bit 49 of LMP Feature Mask Definitions.
* {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
* Same Device Capable (Host).
* Bit 55 of LMP Feature Mask Definitions.
* <b>0x05- 0x07 Reserved</b>
*/
private @LeFlag int mLeFlags = LE_FLAG_GENERAL_DISCOVERY_MODE; // Invalid default
/**
* Main creation method for creating a LE version of {@link OobData}.
*
* <p>This object will allow the caller to call {@link LeBuilder#build()}
* to build the data object or add any option information to the builder.
*
* @param deviceAddressWithType the LE device address plus the address type (7 octets);
* not null.
* @param leDeviceRole whether the device supports Peripheral, Central,
* Both including preference; not null. (1 octet)
* @param confirmationHash Array consisting of {@link OobData#CONFIRMATION_OCTETS} octets
* of data. Data is derived from controller/host stack and is
* required for pairing OOB.
*
* <p>Possible Values:
* {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
* {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
* {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
* Peripheral Preferred
* {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
* 0x04 - 0xFF Reserved
*
* @throws IllegalArgumentException if any of the values fail to be set.
* @throws NullPointerException if any argument is null.
*
* @hide
*/
@SystemApi
public LeBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] deviceAddressWithType,
@LeRole int leDeviceRole) {
requireNonNull(confirmationHash);
requireNonNull(deviceAddressWithType);
if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
throw new IllegalArgumentException("confirmationHash must be "
+ OobData.CONFIRMATION_OCTETS + " octets in length.");
}
this.mConfirmationHash = confirmationHash;
if (deviceAddressWithType.length != OobData.DEVICE_ADDRESS_OCTETS) {
throw new IllegalArgumentException("confirmationHash must be "
+ OobData.DEVICE_ADDRESS_OCTETS+ " octets in length.");
}
this.mDeviceAddressWithType = deviceAddressWithType;
if (leDeviceRole < LE_DEVICE_ROLE_PERIPHERAL_ONLY
|| leDeviceRole > LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL) {
throw new IllegalArgumentException("leDeviceRole must be a valid value.");
}
this.mLeDeviceRole = leDeviceRole;
}
/**
* Sets the Temporary Key value to be used by the LE Security Manager during
* LE pairing.
*
* @param leTemporaryKey byte array that shall be 16 bytes. Please see Bluetooth CSSv6,
* Part A 1.8 for a detailed description.
*
* @return {@link OobData#Builder}
*
* @throws IllegalArgumentException if the leTemporaryKey is an invalid format.
* @throws NullinterException if leTemporaryKey is null.
*
* @hide
*/
@NonNull
@SystemApi
public LeBuilder setLeTemporaryKey(@NonNull byte[] leTemporaryKey) {
requireNonNull(leTemporaryKey);
if (leTemporaryKey.length != LE_TK_OCTETS) {
throw new IllegalArgumentException("leTemporaryKey must be "
+ LE_TK_OCTETS + " octets in length.");
}
this.mLeTemporaryKey = leTemporaryKey;
return this;
}
/**
* @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets
* of data. Data is derived from controller/host stack and is required for pairing OOB.
* Also, randomizerHash may be all 0s or null in which case it becomes all 0s.
*
* @throws IllegalArgumentException if null or incorrect length randomizerHash was passed.
* @throws NullPointerException if randomizerHash is null.
*
* @hide
*/
@NonNull
@SystemApi
public LeBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
requireNonNull(randomizerHash);
if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
throw new IllegalArgumentException("randomizerHash must be "
+ OobData.RANDOMIZER_OCTETS + " octets in length.");
}
this.mRandomizerHash = randomizerHash;
return this;
}
/**
* Sets the LE Flags necessary for the pairing scenario or discovery mode.
*
* @param leFlags enum value representing the 1 octet of data about discovery modes.
*
* <p>Possible LE Flags:
* {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
* {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
* {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
* LMP Feature Mask Definitions.
* {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
* Same Device Capable (Controller) Bit 49 of LMP Feature Mask Definitions.
* {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
* Same Device Capable (Host).
* Bit 55 of LMP Feature Mask Definitions.
* 0x05- 0x07 Reserved
*
* @throws IllegalArgumentException for invalid flag
* @hide
*/
@NonNull
@SystemApi
public LeBuilder setLeFlags(@LeFlag int leFlags) {
if (leFlags < LE_FLAG_LIMITED_DISCOVERY_MODE || leFlags > LE_FLAG_SIMULTANEOUS_HOST) {
throw new IllegalArgumentException("leFlags must be a valid value.");
}
this.mLeFlags = leFlags;
return this;
}
/**
* Validates and builds the {@link OobData} object for LE Security.
*
* @return {@link OobData} with given builder values
*
* @throws IllegalStateException if either of the 2 required fields were not set.
*
* @hide
*/
@NonNull
@SystemApi
public OobData build() {
final OobData oob =
new OobData(this.mDeviceAddressWithType, this.mLeDeviceRole,
this.mConfirmationHash);
// If we have values, set them, otherwise use default
oob.mLeTemporaryKey =
(this.mLeTemporaryKey != null) ? this.mLeTemporaryKey : oob.mLeTemporaryKey;
oob.mLeAppearance = (this.mLeAppearance != null)
? this.mLeAppearance : oob.mLeAppearance;
oob.mLeFlags = (this.mLeFlags != 0xF) ? this.mLeFlags : oob.mLeFlags;
oob.mDeviceName = (this.mDeviceName != null) ? this.mDeviceName : oob.mDeviceName;
oob.mRandomizerHash = this.mRandomizerHash;
return oob;
}
}
/**
* Builds an {@link OobData} object and validates that the required combination
* of values are present to create the Classic specific OobData type.
*
* @hide
*/
@SystemApi
public static final class ClassicBuilder {
// Used by both Classic and LE
/**
* It is recommended that this Hash C is generated anew for each
* pairing.
*
* <p>It should be noted that on passive NFC this isn't possible as the data is static
* and immutable.
*
* @hide
*/
private byte[] mConfirmationHash = null;
/**
* Optional, but adds more validity to the pairing.
*
* <p>If not present a value of 0 is assumed.
*
* @hide
*/
private byte[] mRandomizerHash = new byte[] {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
/**
* The Bluetooth Device user-friendly name presented over Bluetooth Technology.
*
* <p>This is the name that may be displayed to the device user as part of the UI.
*
* @hide
*/
private byte[] mDeviceName = null;
/**
* This length value provides the absolute length of total OOB data block used for
* Bluetooth BR/EDR
*
* <p>OOB communication, which includes the length field itself and the Bluetooth
* Device Address.
*
* <p>The minimum length that may be represented in this field is 8.
*
* @hide
*/
private final byte[] mClassicLength;
/**
* The Bluetooth Device Address is the address to which the OOB data belongs.
*
* <p>The length MUST be {@link OobData#DEVICE_ADDRESS_OCTETS} octets.
*
* <p> Address is encoded in Little Endian order.
*
* <p>e.g. 00:01:02:03:04:05 would be x05x04x03x02x01x00
*
* @hide
*/
private final byte[] mDeviceAddressWithType;
/**
* Class of Device information is to be used to provide a graphical representation
* to the user as part of UI involving operations.
*
* <p>This is not to be used to determine a particular service can be used.
*
* <p>The length MUST be {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
*
* @hide
*/
private byte[] mClassOfDevice = null;
/**
* Main creation method for creating a Classic version of {@link OobData}.
*
* <p>This object will allow the caller to call {@link ClassicBuilder#build()}
* to build the data object or add any option information to the builder.
*
* @param confirmationHash byte array consisting of {@link OobData#CONFIRMATION_OCTETS}
* octets of data. Data is derived from controller/host stack and is required for pairing
* OOB.
* @param classicLength byte array representing the length of data from 8-65535 across 2
* octets (0xXXXX).
* @param deviceAddressWithType byte array representing the Bluetooth Address of the device
* that owns the OOB data. (i.e. the originator) [6 octets]
*
* @throws IllegalArgumentException if any of the values fail to be set.
* @throws NullPointerException if any argument is null.
*
* @hide
*/
@SystemApi
public ClassicBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] classicLength,
@NonNull byte[] deviceAddressWithType) {
requireNonNull(confirmationHash);
requireNonNull(classicLength);
requireNonNull(deviceAddressWithType);
if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
throw new IllegalArgumentException("confirmationHash must be "
+ OobData.CONFIRMATION_OCTETS + " octets in length.");
}
this.mConfirmationHash = confirmationHash;
if (classicLength.length != OOB_LENGTH_OCTETS) {
throw new IllegalArgumentException("classicLength must be "
+ OOB_LENGTH_OCTETS + " octets in length.");
}
this.mClassicLength = classicLength;
if (deviceAddressWithType.length != DEVICE_ADDRESS_OCTETS) {
throw new IllegalArgumentException("deviceAddressWithType must be "
+ DEVICE_ADDRESS_OCTETS + " octets in length.");
}
this.mDeviceAddressWithType = deviceAddressWithType;
}
/**
* @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets
* of data. Data is derived from controller/host stack and is required for pairing OOB.
* Also, randomizerHash may be all 0s or null in which case it becomes all 0s.
*
* @throws IllegalArgumentException if null or incorrect length randomizerHash was passed.
* @throws NullPointerException if randomizerHash is null.
*
* @hide
*/
@NonNull
@SystemApi
public ClassicBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
requireNonNull(randomizerHash);
if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
throw new IllegalArgumentException("randomizerHash must be "
+ OobData.RANDOMIZER_OCTETS + " octets in length.");
}
this.mRandomizerHash = randomizerHash;
return this;
}
/**
* Sets the Bluetooth Device name to be used for UI purposes.
*
* <p>Optional attribute.
*
* @param deviceName byte array representing the name, may be 0 in length, not null.
*
* @return {@link OobData#ClassicBuilder}
*
* @throws NullPointerException if deviceName is null
*
* @hide
*/
@NonNull
@SystemApi
public ClassicBuilder setDeviceName(@NonNull byte[] deviceName) {
requireNonNull(deviceName);
this.mDeviceName = deviceName;
return this;
}
/**
* Sets the Bluetooth Class of Device; used for UI purposes only.
*
* <p>Not an indicator of available services!
*
* <p>Optional attribute.
*
* @param classOfDevice byte array of {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
*
* @return {@link OobData#ClassicBuilder}
*
* @throws IllegalArgumentException if length is not equal to
* {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
* @throws NullPointerException if classOfDevice is null.
*
* @hide
*/
@NonNull
@SystemApi
public ClassicBuilder setClassOfDevice(@NonNull byte[] classOfDevice) {
requireNonNull(classOfDevice);
if (classOfDevice.length != OobData.CLASS_OF_DEVICE_OCTETS) {
throw new IllegalArgumentException("classOfDevice must be "
+ OobData.CLASS_OF_DEVICE_OCTETS + " octets in length.");
}
this.mClassOfDevice = classOfDevice;
return this;
}
/**
* Validates and builds the {@link OobDat object for Classic Security.
*
* @return {@link OobData} with previously given builder values.
*
* @hide
*/
@NonNull
@SystemApi
public OobData build() {
final OobData oob =
new OobData(this.mClassicLength, this.mDeviceAddressWithType,
this.mConfirmationHash);
// If we have values, set them, otherwise use default
oob.mDeviceName = (this.mDeviceName != null) ? this.mDeviceName : oob.mDeviceName;
oob.mClassOfDevice = (this.mClassOfDevice != null)
? this.mClassOfDevice : oob.mClassOfDevice;
oob.mRandomizerHash = this.mRandomizerHash;
return oob;
}
}
// Members (Defaults for Optionals must be set or Parceling fails on NPE)
// Both
private final byte[] mDeviceAddressWithType;
private final byte[] mConfirmationHash;
private byte[] mRandomizerHash = new byte[] {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};
// Default the name to "Bluetooth Device"
private byte[] mDeviceName = new byte[] {
// Bluetooth
0x42, 0x6c, 0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68,
// <space>Device
0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65
};
// Classic
private final byte[] mClassicLength;
private byte[] mClassOfDevice = new byte[CLASS_OF_DEVICE_OCTETS];
// LE
private final @LeRole int mLeDeviceRole;
private byte[] mLeTemporaryKey = new byte[LE_TK_OCTETS];
private byte[] mLeAppearance = new byte[LE_APPEARANCE_OCTETS];
private @LeFlag int mLeFlags = LE_FLAG_LIMITED_DISCOVERY_MODE;
/**
* @return byte array representing the MAC address of a bluetooth device.
* The Address is 6 octets long with a 1 octet address type associated with the address.
*
* <p>For classic this will be 6 byte address plus the default of PUBLIC_ADDRESS Address Type.
* For LE there are more choices for Address Type.
*
* @hide
*/
@NonNull
@SystemApi
public byte[] getDeviceAddressWithType() {
return mDeviceAddressWithType;
}
/**
* @return byte array representing the confirmationHash value
* which is used to confirm the identity to the controller.
*
* @hide
*/
@NonNull
@SystemApi
public byte[] getConfirmationHash() {
return mConfirmationHash;
}
/**
* @return byte array representing the randomizerHash value
* which is used to verify the identity of the controller.
*
* @hide
*/
@NonNull
@SystemApi
public byte[] getRandomizerHash() {
return mRandomizerHash;
}
/**
* @return Device Name used for displaying name in UI.
*
* <p>Also, this will be populated with the LE Local Name if the data is for LE.
*
* @hide
*/
@Nullable
@SystemApi
public byte[] getDeviceName() {
return mDeviceName;
}
/**
* @return byte array representing the oob data length which is the length
* of all of the data including these octets.
*
* @hide
*/
@NonNull
@SystemApi
public byte[] getClassicLength() {
return mClassicLength;
}
/**
* @return byte array representing the class of device for UI display.
*
* <p>Does not indicate services available; for display only.
*
* @hide
*/
@NonNull
@SystemApi
public byte[] getClassOfDevice() {
return mClassOfDevice;
}
/**
* @return Temporary Key used for LE pairing.
*
* @hide
*/
@Nullable
@SystemApi
public byte[] getLeTemporaryKey() {
return mLeTemporaryKey;
}
/**
* @return Appearance used for LE pairing. For use in UI situations
* when determining what sort of icons or text to display regarding
* the device.
*
* @hide
*/
@Nullable
@SystemApi
public byte[] getLeAppearance() {
return mLeAppearance;
}
/**
* @return Flags used to determing discoverable mode to use, BR/EDR Support, and Capability.
*
* <p>Possible LE Flags:
* {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
* {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
* {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
* LMP Feature Mask Definitions.
* {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
* Same Device Capable (Controller).
* Bit 49 of LMP Feature Mask Definitions.
* {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
* Same Device Capable (Host).
* Bit 55 of LMP Feature Mask Definitions.
* <b>0x05- 0x07 Reserved</b>
*
* @hide
*/
@NonNull
@SystemApi
@LeFlag
public int getLeFlags() {
return mLeFlags;
}
/**
* @return the supported and preferred roles of the LE device.
*
* <p>Possible Values:
* {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
* {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
* {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
* Peripheral Preferred
* {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
* 0x04 - 0xFF Reserved
*
* @hide
*/
@NonNull
@SystemApi
@LeRole
public int getLeDeviceRole() {
return mLeDeviceRole;
}
/**
* Classic Security Constructor
*/
private OobData(@NonNull byte[] classicLength, @NonNull byte[] deviceAddressWithType,
@NonNull byte[] confirmationHash) {
mClassicLength = classicLength;
mDeviceAddressWithType = deviceAddressWithType;
mConfirmationHash = confirmationHash;
mLeDeviceRole = -1; // Satisfy final
}
/**
* LE Security Constructor
*/
private OobData(@NonNull byte[] deviceAddressWithType, @LeRole int leDeviceRole,
@NonNull byte[] confirmationHash) {
mDeviceAddressWithType = deviceAddressWithType;
mLeDeviceRole = leDeviceRole;
mConfirmationHash = confirmationHash;
mClassicLength = new byte[OOB_LENGTH_OCTETS]; // Satisfy final
}
private OobData(Parcel in) {
// Both
mDeviceAddressWithType = in.createByteArray();
mConfirmationHash = in.createByteArray();
mRandomizerHash = in.createByteArray();
mDeviceName = in.createByteArray();
// Classic
mClassicLength = in.createByteArray();
mClassOfDevice = in.createByteArray();
// LE
mLeDeviceRole = in.readInt();
mLeTemporaryKey = in.createByteArray();
mLeAppearance = in.createByteArray();
mLeFlags = in.readInt();
}
/**
* @hide
*/
@Override
public int describeContents() {
return 0;
}
/**
* @hide
*/
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
// Both
// Required
out.writeByteArray(mDeviceAddressWithType);
// Required
out.writeByteArray(mConfirmationHash);
// Optional
out.writeByteArray(mRandomizerHash);
// Optional
out.writeByteArray(mDeviceName);
// Classic
// Required
out.writeByteArray(mClassicLength);
// Optional
out.writeByteArray(mClassOfDevice);
// LE
// Required
out.writeInt(mLeDeviceRole);
// Required
out.writeByteArray(mLeTemporaryKey);
// Optional
out.writeByteArray(mLeAppearance);
// Optional
out.writeInt(mLeFlags);
}
// For Parcelable
public static final @android.annotation.NonNull Parcelable.Creator<OobData> CREATOR =
new Parcelable.Creator<OobData>() {
public OobData createFromParcel(Parcel in) {
return new OobData(in);
}
public OobData[] newArray(int size) {
return new OobData[size];
}
};
/**
* @return a {@link String} representation of the OobData object.
*
* @hide
*/
@Override
@NonNull
public String toString() {
return "OobData: \n\t"
// Both
+ "Device Address With Type: " + toHexString(mDeviceAddressWithType) + "\n\t"
+ "Confirmation: " + toHexString(mConfirmationHash) + "\n\t"
+ "Randomizer: " + toHexString(mRandomizerHash) + "\n\t"
+ "Device Name: " + toHexString(mDeviceName) + "\n\t"
// Classic
+ "OobData Length: " + toHexString(mClassicLength) + "\n\t"
+ "Class of Device: " + toHexString(mClassOfDevice) + "\n\t"
// LE
+ "LE Device Role: " + toHexString(mLeDeviceRole) + "\n\t"
+ "LE Temporary Key: " + toHexString(mLeTemporaryKey) + "\n\t"
+ "LE Appearance: " + toHexString(mLeAppearance) + "\n\t"
+ "LE Flags: " + toHexString(mLeFlags) + "\n\t";
}
@NonNull
private String toHexString(int b) {
return toHexString(new byte[] {(byte) b});
}
@NonNull
private String toHexString(byte b) {
return toHexString(new byte[] {b});
}
@NonNull
private String toHexString(byte[] array) {
if (array == null) return "null";
StringBuilder builder = new StringBuilder(array.length * 2);
for (byte b: array) {
builder.append(String.format("%02x", b));
}
return builder.toString();
}
}