| /* |
| * Copyright (C) 2021 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.nearby; |
| |
| import android.annotation.IntRange; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.bluetooth.le.ScanRecord; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| |
| import java.util.Arrays; |
| import java.util.Objects; |
| |
| /** |
| * A data class representing scan result from Nearby Service. Scan result can come from multiple |
| * mediums like BLE, Wi-Fi Aware, and etc. A scan result consists of An encapsulation of various |
| * parameters for requesting nearby scans. |
| * |
| * <p>All scan results generated through {@link NearbyManager} are guaranteed to have a valid |
| * medium, identifier, timestamp (both UTC time and elapsed real-time since boot), and accuracy. All |
| * other parameters are optional. |
| * |
| * @hide |
| */ |
| public final class NearbyDeviceParcelable implements Parcelable { |
| |
| /** Used to read a NearbyDeviceParcelable from a Parcel. */ |
| @NonNull |
| public static final Creator<NearbyDeviceParcelable> CREATOR = |
| new Creator<NearbyDeviceParcelable>() { |
| @Override |
| public NearbyDeviceParcelable createFromParcel(Parcel in) { |
| Builder builder = new Builder(); |
| builder.setDeviceId(in.readLong()); |
| builder.setScanType(in.readInt()); |
| if (in.readInt() == 1) { |
| builder.setName(in.readString()); |
| } |
| builder.setMedium(in.readInt()); |
| builder.setTxPower(in.readInt()); |
| builder.setRssi(in.readInt()); |
| builder.setAction(in.readInt()); |
| builder.setPublicCredential( |
| in.readParcelable( |
| PublicCredential.class.getClassLoader(), |
| PublicCredential.class)); |
| if (in.readInt() == 1) { |
| builder.setFastPairModelId(in.readString()); |
| } |
| if (in.readInt() == 1) { |
| builder.setBluetoothAddress(in.readString()); |
| } |
| if (in.readInt() == 1) { |
| int dataLength = in.readInt(); |
| byte[] data = new byte[dataLength]; |
| in.readByteArray(data); |
| builder.setData(data); |
| } |
| if (in.readInt() == 1) { |
| int saltLength = in.readInt(); |
| byte[] salt = new byte[saltLength]; |
| in.readByteArray(salt); |
| builder.setData(salt); |
| } |
| if (in.readInt() == 1) { |
| builder.setPresenceDevice(in.readParcelable( |
| PresenceDevice.class.getClassLoader(), |
| PresenceDevice.class)); |
| } |
| if (in.readInt() == 1) { |
| int encryptionKeyTagLength = in.readInt(); |
| byte[] keyTag = new byte[encryptionKeyTagLength]; |
| in.readByteArray(keyTag); |
| builder.setData(keyTag); |
| } |
| return builder.build(); |
| } |
| |
| @Override |
| public NearbyDeviceParcelable[] newArray(int size) { |
| return new NearbyDeviceParcelable[size]; |
| } |
| }; |
| |
| private final long mDeviceId; |
| @ScanRequest.ScanType int mScanType; |
| @Nullable private final String mName; |
| @NearbyDevice.Medium private final int mMedium; |
| private final int mTxPower; |
| private final int mRssi; |
| private final int mAction; |
| private final PublicCredential mPublicCredential; |
| @Nullable private final String mBluetoothAddress; |
| @Nullable private final String mFastPairModelId; |
| @Nullable private final byte[] mData; |
| @Nullable private final byte[] mSalt; |
| @Nullable private final PresenceDevice mPresenceDevice; |
| @Nullable private final byte[] mEncryptionKeyTag; |
| |
| private NearbyDeviceParcelable( |
| long deviceId, |
| @ScanRequest.ScanType int scanType, |
| @Nullable String name, |
| int medium, |
| int TxPower, |
| int rssi, |
| int action, |
| PublicCredential publicCredential, |
| @Nullable String fastPairModelId, |
| @Nullable String bluetoothAddress, |
| @Nullable byte[] data, |
| @Nullable byte[] salt, |
| @Nullable PresenceDevice presenceDevice, |
| @Nullable byte[] encryptionKeyTag) { |
| mDeviceId = deviceId; |
| mScanType = scanType; |
| mName = name; |
| mMedium = medium; |
| mTxPower = TxPower; |
| mRssi = rssi; |
| mAction = action; |
| mPublicCredential = publicCredential; |
| mFastPairModelId = fastPairModelId; |
| mBluetoothAddress = bluetoothAddress; |
| mData = data; |
| mSalt = salt; |
| mPresenceDevice = presenceDevice; |
| mEncryptionKeyTag = encryptionKeyTag; |
| } |
| |
| /** No special parcel contents. */ |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| /** |
| * Flatten this NearbyDeviceParcelable in to a Parcel. |
| * |
| * @param dest The Parcel in which the object should be written. |
| * @param flags Additional flags about how the object should be written. |
| */ |
| @Override |
| public void writeToParcel(@NonNull Parcel dest, int flags) { |
| dest.writeLong(mDeviceId); |
| dest.writeInt(mScanType); |
| dest.writeInt(mName == null ? 0 : 1); |
| if (mName != null) { |
| dest.writeString(mName); |
| } |
| dest.writeInt(mMedium); |
| dest.writeInt(mTxPower); |
| dest.writeInt(mRssi); |
| dest.writeInt(mAction); |
| dest.writeParcelable(mPublicCredential, flags); |
| dest.writeInt(mFastPairModelId == null ? 0 : 1); |
| if (mFastPairModelId != null) { |
| dest.writeString(mFastPairModelId); |
| } |
| dest.writeInt(mBluetoothAddress == null ? 0 : 1); |
| if (mBluetoothAddress != null) { |
| dest.writeString(mBluetoothAddress); |
| } |
| dest.writeInt(mData == null ? 0 : 1); |
| if (mData != null) { |
| dest.writeInt(mData.length); |
| dest.writeByteArray(mData); |
| } |
| dest.writeInt(mSalt == null ? 0 : 1); |
| if (mSalt != null) { |
| dest.writeInt(mSalt.length); |
| dest.writeByteArray(mSalt); |
| } |
| dest.writeInt(mPresenceDevice == null ? 0 : 1); |
| if (mPresenceDevice != null) { |
| dest.writeParcelable(mPresenceDevice, /* parcelableFlags= */ 0); |
| } |
| dest.writeInt(mEncryptionKeyTag == null ? 0 : 1); |
| if (mEncryptionKeyTag != null) { |
| dest.writeInt(mEncryptionKeyTag.length); |
| dest.writeByteArray(mEncryptionKeyTag); |
| } |
| } |
| |
| /** Returns a string representation of this ScanRequest. */ |
| @Override |
| public String toString() { |
| return "NearbyDeviceParcelable[" |
| + "deviceId=" |
| + mDeviceId |
| + ", scanType=" |
| + mScanType |
| + ", name=" |
| + mName |
| + ", medium=" |
| + NearbyDevice.mediumToString(mMedium) |
| + ", txPower=" |
| + mTxPower |
| + ", rssi=" |
| + mRssi |
| + ", action=" |
| + mAction |
| + ", bluetoothAddress=" |
| + mBluetoothAddress |
| + ", fastPairModelId=" |
| + mFastPairModelId |
| + ", data=" |
| + Arrays.toString(mData) |
| + ", salt=" |
| + Arrays.toString(mSalt) |
| + "]"; |
| } |
| |
| @Override |
| public boolean equals(Object other) { |
| if (other instanceof NearbyDeviceParcelable) { |
| NearbyDeviceParcelable otherNearbyDeviceParcelable = (NearbyDeviceParcelable) other; |
| return mDeviceId == otherNearbyDeviceParcelable.mDeviceId |
| && mScanType == otherNearbyDeviceParcelable.mScanType |
| && (Objects.equals(mName, otherNearbyDeviceParcelable.mName)) |
| && (mMedium == otherNearbyDeviceParcelable.mMedium) |
| && (mTxPower == otherNearbyDeviceParcelable.mTxPower) |
| && (mRssi == otherNearbyDeviceParcelable.mRssi) |
| && (mAction == otherNearbyDeviceParcelable.mAction) |
| && (Objects.equals( |
| mPublicCredential, otherNearbyDeviceParcelable.mPublicCredential)) |
| && (Objects.equals( |
| mBluetoothAddress, otherNearbyDeviceParcelable.mBluetoothAddress)) |
| && (Objects.equals( |
| mFastPairModelId, otherNearbyDeviceParcelable.mFastPairModelId)) |
| && (Arrays.equals(mData, otherNearbyDeviceParcelable.mData)) |
| && (Arrays.equals(mSalt, otherNearbyDeviceParcelable.mSalt)) |
| && (Objects.equals( |
| mPresenceDevice, otherNearbyDeviceParcelable.mPresenceDevice)) |
| && (Arrays.equals( |
| mEncryptionKeyTag, otherNearbyDeviceParcelable.mEncryptionKeyTag)); |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash( |
| mDeviceId, |
| mScanType, |
| mName, |
| mMedium, |
| mRssi, |
| mAction, |
| mPublicCredential.hashCode(), |
| mBluetoothAddress, |
| mFastPairModelId, |
| Arrays.hashCode(mData), |
| Arrays.hashCode(mSalt), |
| mPresenceDevice, |
| Arrays.hashCode(mEncryptionKeyTag)); |
| } |
| |
| /** |
| * The id of the device. |
| * <p>This id is not a hardware id. It may rotate based on the remote device's broadcasts. |
| * |
| * @hide |
| */ |
| public long getDeviceId() { |
| return mDeviceId; |
| } |
| |
| /** |
| * Returns the type of the scan. |
| * |
| * @hide |
| */ |
| @ScanRequest.ScanType |
| public int getScanType() { |
| return mScanType; |
| } |
| |
| /** |
| * Gets the name of the NearbyDeviceParcelable. Returns {@code null} If there is no name. |
| * |
| * Used in Fast Pair. |
| */ |
| @Nullable |
| public String getName() { |
| return mName; |
| } |
| |
| /** |
| * Gets the {@link android.nearby.NearbyDevice.Medium} of the NearbyDeviceParcelable over which |
| * it is discovered. |
| * |
| * Used in Fast Pair and Nearby Presence. |
| */ |
| @NearbyDevice.Medium |
| public int getMedium() { |
| return mMedium; |
| } |
| |
| /** |
| * Gets the transmission power in dBm. |
| * |
| * Used in Fast Pair. |
| * |
| * @hide |
| */ |
| @IntRange(from = -127, to = 126) |
| public int getTxPower() { |
| return mTxPower; |
| } |
| |
| /** |
| * Gets the received signal strength in dBm. |
| * |
| * Used in Fast Pair and Nearby Presence. |
| */ |
| @IntRange(from = -127, to = 126) |
| public int getRssi() { |
| return mRssi; |
| } |
| |
| /** |
| * Gets the Action. |
| * |
| * Used in Nearby Presence. |
| * |
| * @hide |
| */ |
| @IntRange(from = -127, to = 126) |
| public int getAction() { |
| return mAction; |
| } |
| |
| /** |
| * Gets the public credential. |
| * |
| * Used in Nearby Presence. |
| * |
| * @hide |
| */ |
| @NonNull |
| public PublicCredential getPublicCredential() { |
| return mPublicCredential; |
| } |
| |
| /** |
| * Gets the Fast Pair identifier. Returns {@code null} if there is no Model ID or this is not a |
| * Fast Pair device. |
| * |
| * Used in Fast Pair. |
| */ |
| @Nullable |
| public String getFastPairModelId() { |
| return mFastPairModelId; |
| } |
| |
| /** |
| * Gets the Bluetooth device hardware address. Returns {@code null} if the device is not |
| * discovered by Bluetooth. |
| * |
| * Used in Fast Pair. |
| */ |
| @Nullable |
| public String getBluetoothAddress() { |
| return mBluetoothAddress; |
| } |
| |
| /** |
| * Gets the raw data from the scanning. |
| * Returns {@code null} if there is no extra data or this is not a Fast Pair device. |
| * |
| * Used in Fast Pair. |
| */ |
| @Nullable |
| public byte[] getData() { |
| return mData; |
| } |
| |
| /** |
| * Gets the salt in the advertisement from the Nearby Presence device. |
| * Returns {@code null} if this is not a Nearby Presence device. |
| * |
| * Used in Nearby Presence. |
| */ |
| @Nullable |
| public byte[] getSalt() { |
| return mSalt; |
| } |
| |
| /** |
| * Gets the {@link PresenceDevice} Nearby Presence device. This field is |
| * for Fast Pair client only. |
| */ |
| @Nullable |
| public PresenceDevice getPresenceDevice() { |
| return mPresenceDevice; |
| } |
| |
| /** |
| * Gets the encryption key tag calculated from advertisement |
| * Returns {@code null} if the data is not encrypted or this is not a Presence device. |
| * |
| * Used in Presence. |
| */ |
| @Nullable |
| public byte[] getEncryptionKeyTag() { |
| return mEncryptionKeyTag; |
| } |
| |
| /** Builder class for {@link NearbyDeviceParcelable}. */ |
| public static final class Builder { |
| private long mDeviceId = -1; |
| @Nullable private String mName; |
| @NearbyDevice.Medium private int mMedium; |
| private int mTxPower; |
| private int mRssi; |
| private int mAction; |
| private PublicCredential mPublicCredential; |
| @ScanRequest.ScanType int mScanType; |
| @Nullable private String mFastPairModelId; |
| @Nullable private String mBluetoothAddress; |
| @Nullable private byte[] mData; |
| @Nullable private byte[] mSalt; |
| @Nullable private PresenceDevice mPresenceDevice; |
| @Nullable private byte[] mEncryptionKeyTag; |
| |
| /** Sets the id of the device. */ |
| public Builder setDeviceId(long deviceId) { |
| this.mDeviceId = deviceId; |
| return this; |
| } |
| |
| /** |
| * Sets the scan type of the NearbyDeviceParcelable. |
| * |
| * @hide |
| */ |
| public Builder setScanType(@ScanRequest.ScanType int scanType) { |
| mScanType = scanType; |
| return this; |
| } |
| |
| /** |
| * Sets the name of the scanned device. |
| * |
| * @param name The local name of the scanned device. |
| */ |
| @NonNull |
| public Builder setName(@Nullable String name) { |
| mName = name; |
| return this; |
| } |
| |
| /** |
| * Sets the medium over which the device is discovered. |
| * |
| * @param medium The {@link NearbyDevice.Medium} over which the device is discovered. |
| */ |
| @NonNull |
| public Builder setMedium(@NearbyDevice.Medium int medium) { |
| mMedium = medium; |
| return this; |
| } |
| |
| /** |
| * Sets the transmission power of the discovered device. |
| * |
| * @param txPower The transmission power in dBm. |
| * @hide |
| */ |
| @NonNull |
| public Builder setTxPower(int txPower) { |
| mTxPower = txPower; |
| return this; |
| } |
| |
| /** |
| * Sets the RSSI between scanned device and the discovered device. |
| * |
| * @param rssi The received signal strength in dBm. |
| */ |
| @NonNull |
| public Builder setRssi(@IntRange(from = -127, to = 126) int rssi) { |
| mRssi = rssi; |
| return this; |
| } |
| |
| /** |
| * Sets the action from the discovered device. |
| * |
| * @param action The action of the discovered device. |
| * @hide |
| */ |
| @NonNull |
| public Builder setAction(int action) { |
| mAction = action; |
| return this; |
| } |
| |
| /** |
| * Sets the public credential of the discovered device. |
| * |
| * @param publicCredential The public credential. |
| * @hide |
| */ |
| @NonNull |
| public Builder setPublicCredential(@NonNull PublicCredential publicCredential) { |
| mPublicCredential = publicCredential; |
| return this; |
| } |
| |
| /** |
| * Sets the Fast Pair model Id. |
| * |
| * @param fastPairModelId Fast Pair device identifier. |
| */ |
| @NonNull |
| public Builder setFastPairModelId(@Nullable String fastPairModelId) { |
| mFastPairModelId = fastPairModelId; |
| return this; |
| } |
| |
| /** |
| * Sets the bluetooth address. |
| * |
| * @param bluetoothAddress The hardware address of the bluetooth device. |
| */ |
| @NonNull |
| public Builder setBluetoothAddress(@Nullable String bluetoothAddress) { |
| mBluetoothAddress = bluetoothAddress; |
| return this; |
| } |
| |
| /** |
| * Sets the scanned raw data. |
| * |
| * @param data raw data scanned, like {@link ScanRecord#getServiceData()} if scanned by |
| * Bluetooth. |
| */ |
| @NonNull |
| public Builder setData(@Nullable byte[] data) { |
| mData = data; |
| return this; |
| } |
| |
| /** |
| * Sets the encryption key tag calculated from the advertisement. |
| * |
| * @param encryptionKeyTag calculated from identity scanned from the advertisement |
| */ |
| @NonNull |
| public Builder setEncryptionKeyTag(@Nullable byte[] encryptionKeyTag) { |
| mEncryptionKeyTag = encryptionKeyTag; |
| return this; |
| } |
| |
| /** |
| * Sets the slat in the advertisement from the Nearby Presence device. |
| * |
| * @param salt in the advertisement from the Nearby Presence device. |
| */ |
| @NonNull |
| public Builder setSalt(@Nullable byte[] salt) { |
| mSalt = salt; |
| return this; |
| } |
| |
| /** |
| * Sets the {@link PresenceDevice} if there is any. |
| * The current {@link NearbyDeviceParcelable} can be seen as the wrapper of the |
| * {@link PresenceDevice}. |
| */ |
| @Nullable |
| public Builder setPresenceDevice(@Nullable PresenceDevice presenceDevice) { |
| mPresenceDevice = presenceDevice; |
| return this; |
| } |
| |
| /** Builds a ScanResult. */ |
| @NonNull |
| public NearbyDeviceParcelable build() { |
| return new NearbyDeviceParcelable( |
| mDeviceId, |
| mScanType, |
| mName, |
| mMedium, |
| mTxPower, |
| mRssi, |
| mAction, |
| mPublicCredential, |
| mFastPairModelId, |
| mBluetoothAddress, |
| mData, |
| mSalt, |
| mPresenceDevice, |
| mEncryptionKeyTag); |
| } |
| } |
| } |