1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.nearby; 18 19 import android.annotation.IntRange; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 25 import java.util.ArrayList; 26 import java.util.Arrays; 27 import java.util.List; 28 import java.util.Objects; 29 30 /** 31 * A class represents a Fast Pair device that can be discovered by multiple mediums. 32 * 33 * @hide 34 */ 35 public class FastPairDevice extends NearbyDevice implements Parcelable { 36 /** 37 * Used to read a FastPairDevice from a Parcel. 38 */ 39 public static final Creator<FastPairDevice> CREATOR = new Creator<FastPairDevice>() { 40 @Override 41 public FastPairDevice createFromParcel(Parcel in) { 42 FastPairDevice.Builder builder = new FastPairDevice.Builder(); 43 if (in.readInt() == 1) { 44 builder.setName(in.readString()); 45 } 46 int size = in.readInt(); 47 for (int i = 0; i < size; i++) { 48 builder.addMedium(in.readInt()); 49 } 50 builder.setRssi(in.readInt()); 51 builder.setTxPower(in.readInt()); 52 if (in.readInt() == 1) { 53 builder.setModelId(in.readString()); 54 } 55 builder.setBluetoothAddress(in.readString()); 56 if (in.readInt() == 1) { 57 int dataLength = in.readInt(); 58 byte[] data = new byte[dataLength]; 59 in.readByteArray(data); 60 builder.setData(data); 61 } 62 return builder.build(); 63 } 64 65 @Override 66 public FastPairDevice[] newArray(int size) { 67 return new FastPairDevice[size]; 68 } 69 }; 70 71 // The transmit power in dBm. Valid range is [-127, 126]. a 72 // See android.bluetooth.le.ScanResult#getTxPower 73 private int mTxPower; 74 75 // Some OEM devices devices don't have model Id. 76 @Nullable private final String mModelId; 77 78 // Bluetooth hardware address as string. Can be read from BLE ScanResult. 79 private final String mBluetoothAddress; 80 81 @Nullable 82 private final byte[] mData; 83 84 /** 85 * Creates a new FastPairDevice. 86 * 87 * @param name Name of the FastPairDevice. Can be {@code null} if there is no name. 88 * @param mediums The {@link Medium}s over which the device is discovered. 89 * @param rssi The received signal strength in dBm. 90 * @param txPower The transmit power in dBm. Valid range is [-127, 126]. 91 * @param modelId The identifier of the Fast Pair device. 92 * Can be {@code null} if there is no Model ID. 93 * @param bluetoothAddress The hardware address of this BluetoothDevice. 94 * @param data Extra data for a Fast Pair device. 95 */ FastPairDevice(@ullable String name, List<Integer> mediums, int rssi, int txPower, @Nullable String modelId, @NonNull String bluetoothAddress, @Nullable byte[] data)96 public FastPairDevice(@Nullable String name, 97 List<Integer> mediums, 98 int rssi, 99 int txPower, 100 @Nullable String modelId, 101 @NonNull String bluetoothAddress, 102 @Nullable byte[] data) { 103 super(name, mediums, rssi); 104 this.mTxPower = txPower; 105 this.mModelId = modelId; 106 this.mBluetoothAddress = bluetoothAddress; 107 this.mData = data; 108 } 109 110 /** 111 * Gets the transmit power in dBm. A value of 112 * android.bluetooth.le.ScanResult#TX_POWER_NOT_PRESENT 113 * indicates that the TX power is not present. 114 */ 115 @IntRange(from = -127, to = 126) getTxPower()116 public int getTxPower() { 117 return mTxPower; 118 } 119 120 /** 121 * Gets the identifier of the Fast Pair device. Can be {@code null} if there is no Model ID. 122 */ 123 @Nullable getModelId()124 public String getModelId() { 125 return this.mModelId; 126 } 127 128 /** 129 * Gets the hardware address of this BluetoothDevice. 130 */ 131 @NonNull getBluetoothAddress()132 public String getBluetoothAddress() { 133 return mBluetoothAddress; 134 } 135 136 /** 137 * Gets the extra data for a Fast Pair device. Can be {@code null} if there is extra data. 138 * 139 * @hide 140 */ 141 @Nullable getData()142 public byte[] getData() { 143 return mData; 144 } 145 146 /** 147 * No special parcel contents. 148 */ 149 @Override describeContents()150 public int describeContents() { 151 return 0; 152 } 153 154 /** 155 * Returns a string representation of this FastPairDevice. 156 */ 157 @Override toString()158 public String toString() { 159 StringBuilder stringBuilder = new StringBuilder(); 160 stringBuilder.append("FastPairDevice ["); 161 String name = getName(); 162 if (getName() != null && !name.isEmpty()) { 163 stringBuilder.append("name=").append(name).append(", "); 164 } 165 stringBuilder.append("medium={"); 166 for (int medium: getMediums()) { 167 stringBuilder.append(mediumToString(medium)); 168 } 169 stringBuilder.append("} rssi=").append(getRssi()); 170 stringBuilder.append(" txPower=").append(mTxPower); 171 stringBuilder.append(" modelId=").append(mModelId); 172 stringBuilder.append(" bluetoothAddress=").append(mBluetoothAddress); 173 stringBuilder.append("]"); 174 return stringBuilder.toString(); 175 } 176 177 @Override equals(Object other)178 public boolean equals(Object other) { 179 if (other instanceof FastPairDevice) { 180 FastPairDevice otherDevice = (FastPairDevice) other; 181 if (!super.equals(other)) { 182 return false; 183 } 184 return mTxPower == otherDevice.mTxPower 185 && Objects.equals(mModelId, otherDevice.mModelId) 186 && Objects.equals(mBluetoothAddress, otherDevice.mBluetoothAddress) 187 && Arrays.equals(mData, otherDevice.mData); 188 } 189 return false; 190 } 191 192 @Override hashCode()193 public int hashCode() { 194 return Objects.hash( 195 getName(), getMediums(), getRssi(), mTxPower, mModelId, mBluetoothAddress, 196 Arrays.hashCode(mData)); 197 } 198 199 @Override writeToParcel(@onNull Parcel dest, int flags)200 public void writeToParcel(@NonNull Parcel dest, int flags) { 201 String name = getName(); 202 dest.writeInt(name == null ? 0 : 1); 203 if (name != null) { 204 dest.writeString(name); 205 } 206 List<Integer> mediums = getMediums(); 207 dest.writeInt(mediums.size()); 208 for (int medium : mediums) { 209 dest.writeInt(medium); 210 } 211 dest.writeInt(getRssi()); 212 dest.writeInt(mTxPower); 213 dest.writeInt(mModelId == null ? 0 : 1); 214 if (mModelId != null) { 215 dest.writeString(mModelId); 216 } 217 dest.writeString(mBluetoothAddress); 218 dest.writeInt(mData == null ? 0 : 1); 219 if (mData != null) { 220 dest.writeInt(mData.length); 221 dest.writeByteArray(mData); 222 } 223 } 224 225 /** 226 * A builder class for {@link FastPairDevice} 227 * 228 * @hide 229 */ 230 public static final class Builder { 231 private final List<Integer> mMediums; 232 233 @Nullable private String mName; 234 private int mRssi; 235 private int mTxPower; 236 @Nullable private String mModelId; 237 private String mBluetoothAddress; 238 @Nullable private byte[] mData; 239 Builder()240 public Builder() { 241 mMediums = new ArrayList<>(); 242 } 243 244 /** 245 * Sets the name of the Fast Pair device. 246 * 247 * @param name Name of the FastPairDevice. Can be {@code null} if there is no name. 248 */ 249 @NonNull setName(@ullable String name)250 public Builder setName(@Nullable String name) { 251 mName = name; 252 return this; 253 } 254 255 /** 256 * Sets the medium over which the Fast Pair device is discovered. 257 * 258 * @param medium The {@link Medium} over which the device is discovered. 259 */ 260 @NonNull addMedium(@edium int medium)261 public Builder addMedium(@Medium int medium) { 262 mMediums.add(medium); 263 return this; 264 } 265 266 /** 267 * Sets the RSSI between the scan device and the discovered Fast Pair device. 268 * 269 * @param rssi The received signal strength in dBm. 270 */ 271 @NonNull setRssi(@ntRangefrom = -127, to = 126) int rssi)272 public Builder setRssi(@IntRange(from = -127, to = 126) int rssi) { 273 mRssi = rssi; 274 return this; 275 } 276 277 /** 278 * Sets the txPower. 279 * 280 * @param txPower The transmit power in dBm 281 */ 282 @NonNull setTxPower(@ntRangefrom = -127, to = 126) int txPower)283 public Builder setTxPower(@IntRange(from = -127, to = 126) int txPower) { 284 mTxPower = txPower; 285 return this; 286 } 287 288 /** 289 * Sets the model Id of this Fast Pair device. 290 * 291 * @param modelId The identifier of the Fast Pair device. Can be {@code null} 292 * if there is no Model ID. 293 */ 294 @NonNull setModelId(@ullable String modelId)295 public Builder setModelId(@Nullable String modelId) { 296 mModelId = modelId; 297 return this; 298 } 299 300 /** 301 * Sets the hardware address of this BluetoothDevice. 302 * 303 * @param bluetoothAddress The hardware address of this BluetoothDevice. 304 */ 305 @NonNull setBluetoothAddress(@onNull String bluetoothAddress)306 public Builder setBluetoothAddress(@NonNull String bluetoothAddress) { 307 Objects.requireNonNull(bluetoothAddress); 308 mBluetoothAddress = bluetoothAddress; 309 return this; 310 } 311 312 /** 313 * Sets the raw data for a FastPairDevice. Can be {@code null} if there is no extra data. 314 * 315 * @hide 316 */ 317 @NonNull setData(@ullable byte[] data)318 public Builder setData(@Nullable byte[] data) { 319 mData = data; 320 return this; 321 } 322 323 /** 324 * Builds a FastPairDevice and return it. 325 */ 326 @NonNull build()327 public FastPairDevice build() { 328 return new FastPairDevice(mName, mMediums, mRssi, mTxPower, mModelId, 329 mBluetoothAddress, mData); 330 } 331 } 332 } 333