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