AdvertiseData.java revision 67c01a4b6d890212fb4647973a627e25a3a9788b
1/* 2 * Copyright (C) 2014 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 17package android.bluetooth.le; 18 19import android.annotation.Nullable; 20import android.bluetooth.BluetoothUuid; 21import android.os.Parcel; 22import android.os.ParcelUuid; 23import android.os.Parcelable; 24 25import java.util.ArrayList; 26import java.util.Arrays; 27import java.util.List; 28import java.util.Objects; 29 30/** 31 * Advertise data packet container for Bluetooth LE advertising. This represents the data to be 32 * advertised as well as the scan response data for active scans. 33 * <p> 34 * Use {@link AdvertiseData.Builder} to create an instance of {@link AdvertiseData} to be 35 * advertised. 36 * 37 * @see BluetoothLeAdvertiser 38 * @see ScanRecord 39 */ 40public final class AdvertiseData implements Parcelable { 41 42 @Nullable 43 private final List<ParcelUuid> mServiceUuids; 44 45 private final int mManufacturerId; 46 @Nullable 47 private final byte[] mManufacturerSpecificData; 48 49 @Nullable 50 private final ParcelUuid mServiceDataUuid; 51 @Nullable 52 private final byte[] mServiceData; 53 54 private final boolean mIncludeTxPowerLevel; 55 private final boolean mIncludeDeviceName; 56 57 private AdvertiseData(List<ParcelUuid> serviceUuids, 58 ParcelUuid serviceDataUuid, byte[] serviceData, 59 int manufacturerId, 60 byte[] manufacturerSpecificData, boolean includeTxPowerLevel, 61 boolean includeDeviceName) { 62 mServiceUuids = serviceUuids; 63 mManufacturerId = manufacturerId; 64 mManufacturerSpecificData = manufacturerSpecificData; 65 mServiceDataUuid = serviceDataUuid; 66 mServiceData = serviceData; 67 mIncludeTxPowerLevel = includeTxPowerLevel; 68 mIncludeDeviceName = includeDeviceName; 69 } 70 71 /** 72 * Returns a list of service UUIDs within the advertisement that are used to identify the 73 * Bluetooth GATT services. 74 */ 75 public List<ParcelUuid> getServiceUuids() { 76 return mServiceUuids; 77 } 78 79 /** 80 * Returns the manufacturer identifier, which is a non-negative number assigned by Bluetooth 81 * SIG. 82 */ 83 public int getManufacturerId() { 84 return mManufacturerId; 85 } 86 87 /** 88 * Returns the manufacturer specific data which is the content of manufacturer specific data 89 * field. The first 2 bytes of the data contain the company id. 90 */ 91 public byte[] getManufacturerSpecificData() { 92 return mManufacturerSpecificData; 93 } 94 95 /** 96 * Returns a 16-bit UUID of the service that the service data is associated with. 97 */ 98 public ParcelUuid getServiceDataUuid() { 99 return mServiceDataUuid; 100 } 101 102 /** 103 * Returns service data. 104 */ 105 public byte[] getServiceData() { 106 return mServiceData; 107 } 108 109 /** 110 * Whether the transmission power level will be included in the advertisement packet. 111 */ 112 public boolean getIncludeTxPowerLevel() { 113 return mIncludeTxPowerLevel; 114 } 115 116 /** 117 * Whether the device name will be included in the advertisement packet. 118 */ 119 public boolean getIncludeDeviceName() { 120 return mIncludeDeviceName; 121 } 122 123 /** 124 * @hide 125 */ 126 @Override 127 public int hashCode() { 128 return Objects.hash(mServiceUuids, mManufacturerId, mManufacturerSpecificData, 129 mServiceDataUuid, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel); 130 } 131 132 /** 133 * @hide 134 */ 135 @Override 136 public boolean equals(Object obj) { 137 if (this == obj) { 138 return true; 139 } 140 if (obj == null || getClass() != obj.getClass()) { 141 return false; 142 } 143 AdvertiseData other = (AdvertiseData) obj; 144 return Objects.equals(mServiceUuids, other.mServiceUuids) && 145 mManufacturerId == other.mManufacturerId && 146 Objects.deepEquals(mManufacturerSpecificData, other.mManufacturerSpecificData) && 147 Objects.equals(mServiceDataUuid, other.mServiceDataUuid) && 148 Objects.deepEquals(mServiceData, other.mServiceData) && 149 mIncludeDeviceName == other.mIncludeDeviceName && 150 mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; 151 } 152 153 @Override 154 public String toString() { 155 return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerId=" 156 + mManufacturerId + ", mManufacturerSpecificData=" 157 + Arrays.toString(mManufacturerSpecificData) + ", mServiceDataUuid=" 158 + mServiceDataUuid + ", mServiceData=" + Arrays.toString(mServiceData) 159 + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" 160 + mIncludeDeviceName + "]"; 161 } 162 163 @Override 164 public int describeContents() { 165 return 0; 166 } 167 168 @Override 169 public void writeToParcel(Parcel dest, int flags) { 170 dest.writeList(mServiceUuids); 171 172 dest.writeInt(mManufacturerId); 173 if (mManufacturerSpecificData == null) { 174 dest.writeInt(0); 175 } else { 176 dest.writeInt(1); 177 dest.writeInt(mManufacturerSpecificData.length); 178 dest.writeByteArray(mManufacturerSpecificData); 179 } 180 dest.writeParcelable(mServiceDataUuid, flags); 181 if (mServiceData == null) { 182 dest.writeInt(0); 183 } else { 184 dest.writeInt(1); 185 dest.writeInt(mServiceData.length); 186 dest.writeByteArray(mServiceData); 187 } 188 dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0)); 189 dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0)); 190 } 191 192 /** 193 * @hide 194 */ 195 public static final Parcelable.Creator<AdvertiseData> CREATOR = 196 new Creator<AdvertiseData>() { 197 @Override 198 public AdvertiseData[] newArray(int size) { 199 return new AdvertiseData[size]; 200 } 201 202 @Override 203 public AdvertiseData createFromParcel(Parcel in) { 204 Builder builder = new Builder(); 205 @SuppressWarnings("unchecked") 206 List<ParcelUuid> uuids = in.readArrayList(ParcelUuid.class.getClassLoader()); 207 if (uuids != null) { 208 for (ParcelUuid uuid : uuids) { 209 builder.addServiceUuid(uuid); 210 } 211 } 212 int manufacturerId = in.readInt(); 213 if (in.readInt() == 1) { 214 int manufacturerDataLength = in.readInt(); 215 byte[] manufacturerData = new byte[manufacturerDataLength]; 216 in.readByteArray(manufacturerData); 217 builder.setManufacturerData(manufacturerId, manufacturerData); 218 } 219 ParcelUuid serviceDataUuid = in.readParcelable( 220 ParcelUuid.class.getClassLoader()); 221 if (in.readInt() == 1) { 222 int serviceDataLength = in.readInt(); 223 byte[] serviceData = new byte[serviceDataLength]; 224 in.readByteArray(serviceData); 225 builder.setServiceData(serviceDataUuid, serviceData); 226 } 227 builder.setIncludeTxPowerLevel(in.readByte() == 1); 228 builder.setIncludeDeviceName(in.readByte() == 1); 229 return builder.build(); 230 } 231 }; 232 233 /** 234 * Builder for {@link AdvertiseData}. 235 */ 236 public static final class Builder { 237 @Nullable 238 private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>(); 239 private int mManufacturerId = -1; 240 @Nullable 241 private byte[] mManufacturerSpecificData; 242 @Nullable 243 private ParcelUuid mServiceDataUuid; 244 @Nullable 245 private byte[] mServiceData; 246 private boolean mIncludeTxPowerLevel; 247 private boolean mIncludeDeviceName; 248 249 /** 250 * Add a service UUID to advertise data. 251 * 252 * @param serviceUuid A service UUID to be advertised. 253 * @throws IllegalArgumentException If the {@code serviceUuids} are null. 254 */ 255 public Builder addServiceUuid(ParcelUuid serviceUuid) { 256 if (serviceUuid == null) { 257 throw new IllegalArgumentException("serivceUuids are null"); 258 } 259 mServiceUuids.add(serviceUuid); 260 return this; 261 } 262 263 /** 264 * Add service data to advertise data. 265 * 266 * @param serviceDataUuid 16-bit UUID of the service the data is associated with 267 * @param serviceData Service data 268 * @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is 269 * empty. 270 */ 271 public Builder setServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) { 272 if (serviceDataUuid == null || serviceData == null) { 273 throw new IllegalArgumentException( 274 "serviceDataUuid or serviceDataUuid is null"); 275 } 276 mServiceDataUuid = serviceDataUuid; 277 mServiceData = serviceData; 278 return this; 279 } 280 281 /** 282 * Set manufacturer specific data. 283 * <p> 284 * Please refer to the Bluetooth Assigned Numbers document provided by the <a 285 * href="https://www.bluetooth.org">Bluetooth SIG</a> for a list of existing company 286 * identifiers. 287 * 288 * @param manufacturerId Manufacturer ID assigned by Bluetooth SIG. 289 * @param manufacturerSpecificData Manufacturer specific data 290 * @throws IllegalArgumentException If the {@code manufacturerId} is negative or 291 * {@code manufacturerSpecificData} is null. 292 */ 293 public Builder setManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) { 294 if (manufacturerId < 0) { 295 throw new IllegalArgumentException( 296 "invalid manufacturerId - " + manufacturerId); 297 } 298 if (manufacturerSpecificData == null) { 299 throw new IllegalArgumentException("manufacturerSpecificData is null"); 300 } 301 mManufacturerId = manufacturerId; 302 mManufacturerSpecificData = manufacturerSpecificData; 303 return this; 304 } 305 306 /** 307 * Whether the transmission power level should be included in the advertise packet. Tx power 308 * level field takes 3 bytes in advertise packet. 309 */ 310 public Builder setIncludeTxPowerLevel(boolean includeTxPowerLevel) { 311 mIncludeTxPowerLevel = includeTxPowerLevel; 312 return this; 313 } 314 315 /** 316 * Set whether the device name should be included in advertise packet. 317 */ 318 public Builder setIncludeDeviceName(boolean includeDeviceName) { 319 mIncludeDeviceName = includeDeviceName; 320 return this; 321 } 322 323 /** 324 * Build the {@link AdvertiseData}. 325 */ 326 public AdvertiseData build() { 327 return new AdvertiseData(mServiceUuids, 328 mServiceDataUuid, 329 mServiceData, mManufacturerId, mManufacturerSpecificData, 330 mIncludeTxPowerLevel, mIncludeDeviceName); 331 } 332 } 333} 334