1/*
2 * Copyright (C) 2013 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 */
16package android.bluetooth;
17
18import android.os.Parcel;
19import android.os.ParcelUuid;
20import android.os.Parcelable;
21
22import java.util.ArrayList;
23import java.util.List;
24import java.util.UUID;
25
26/**
27 * Represents a Bluetooth GATT Service
28 *
29 * <p> Gatt Service contains a collection of {@link BluetoothGattCharacteristic},
30 * as well as referenced services.
31 */
32public class BluetoothGattService implements Parcelable {
33
34    /**
35     * Primary service
36     */
37    public static final int SERVICE_TYPE_PRIMARY = 0;
38
39    /**
40     * Secondary service (included by primary services)
41     */
42    public static final int SERVICE_TYPE_SECONDARY = 1;
43
44
45    /**
46     * The remote device his service is associated with.
47     * This applies to client applications only.
48     *
49     * @hide
50     */
51    protected BluetoothDevice mDevice;
52
53    /**
54     * The UUID of this service.
55     *
56     * @hide
57     */
58    protected UUID mUuid;
59
60    /**
61     * Instance ID for this service.
62     *
63     * @hide
64     */
65    protected int mInstanceId;
66
67    /**
68     * Handle counter override (for conformance testing).
69     *
70     * @hide
71     */
72    protected int mHandles = 0;
73
74    /**
75     * Service type (Primary/Secondary).
76     *
77     * @hide
78     */
79    protected int mServiceType;
80
81    /**
82     * List of characteristics included in this service.
83     */
84    protected List<BluetoothGattCharacteristic> mCharacteristics;
85
86    /**
87     * List of included services for this service.
88     */
89    protected List<BluetoothGattService> mIncludedServices;
90
91    /**
92     * Whether the service uuid should be advertised.
93     */
94    private boolean mAdvertisePreferred;
95
96    /**
97     * Create a new BluetoothGattService.
98     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
99     *
100     * @param uuid The UUID for this service
101     * @param serviceType The type of this service,
102     * {@link BluetoothGattService#SERVICE_TYPE_PRIMARY}
103     * or {@link BluetoothGattService#SERVICE_TYPE_SECONDARY}
104     */
105    public BluetoothGattService(UUID uuid, int serviceType) {
106        mDevice = null;
107        mUuid = uuid;
108        mInstanceId = 0;
109        mServiceType = serviceType;
110        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
111        mIncludedServices = new ArrayList<BluetoothGattService>();
112    }
113
114    /**
115     * Create a new BluetoothGattService
116     *
117     * @hide
118     */
119    /*package*/ BluetoothGattService(BluetoothDevice device, UUID uuid,
120            int instanceId, int serviceType) {
121        mDevice = device;
122        mUuid = uuid;
123        mInstanceId = instanceId;
124        mServiceType = serviceType;
125        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
126        mIncludedServices = new ArrayList<BluetoothGattService>();
127    }
128
129    /**
130     * Create a new BluetoothGattService
131     *
132     * @hide
133     */
134    public BluetoothGattService(UUID uuid, int instanceId, int serviceType) {
135        mDevice = null;
136        mUuid = uuid;
137        mInstanceId = instanceId;
138        mServiceType = serviceType;
139        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
140        mIncludedServices = new ArrayList<BluetoothGattService>();
141    }
142
143    /**
144     * @hide
145     */
146    public int describeContents() {
147        return 0;
148    }
149
150    @Override
151    public void writeToParcel(Parcel out, int flags) {
152        out.writeParcelable(new ParcelUuid(mUuid), 0);
153        out.writeInt(mInstanceId);
154        out.writeInt(mServiceType);
155        out.writeTypedList(mCharacteristics);
156
157        ArrayList<BluetoothGattIncludedService> includedServices =
158                new ArrayList<BluetoothGattIncludedService>(mIncludedServices.size());
159        for (BluetoothGattService s : mIncludedServices) {
160            includedServices.add(new BluetoothGattIncludedService(s.getUuid(),
161                    s.getInstanceId(), s.getType()));
162        }
163        out.writeTypedList(includedServices);
164    }
165
166    public static final Parcelable.Creator<BluetoothGattService> CREATOR =
167            new Parcelable.Creator<BluetoothGattService>() {
168        public BluetoothGattService createFromParcel(Parcel in) {
169            return new BluetoothGattService(in);
170        }
171
172        public BluetoothGattService[] newArray(int size) {
173            return new BluetoothGattService[size];
174        }
175    };
176
177    private BluetoothGattService(Parcel in) {
178        mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
179        mInstanceId = in.readInt();
180        mServiceType = in.readInt();
181
182        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
183
184        ArrayList<BluetoothGattCharacteristic> chrcs =
185                in.createTypedArrayList(BluetoothGattCharacteristic.CREATOR);
186        if (chrcs != null) {
187            for (BluetoothGattCharacteristic chrc : chrcs) {
188                chrc.setService(this);
189                mCharacteristics.add(chrc);
190            }
191        }
192
193        mIncludedServices = new ArrayList<BluetoothGattService>();
194
195        ArrayList<BluetoothGattIncludedService> inclSvcs =
196                in.createTypedArrayList(BluetoothGattIncludedService.CREATOR);
197        if (chrcs != null) {
198            for (BluetoothGattIncludedService isvc : inclSvcs) {
199                mIncludedServices.add(new BluetoothGattService(null, isvc.getUuid(),
200                        isvc.getInstanceId(), isvc.getType()));
201            }
202        }
203    }
204
205    /**
206     * Returns the device associated with this service.
207     *
208     * @hide
209     */
210    /*package*/ BluetoothDevice getDevice() {
211        return mDevice;
212    }
213
214    /**
215     * Returns the device associated with this service.
216     *
217     * @hide
218     */
219    /*package*/ void setDevice(BluetoothDevice device) {
220        mDevice = device;
221    }
222
223    /**
224     * Add an included service to this service.
225     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
226     *
227     * @param service The service to be added
228     * @return true, if the included service was added to the service
229     */
230    public boolean addService(BluetoothGattService service) {
231        mIncludedServices.add(service);
232        return true;
233    }
234
235    /**
236     * Add a characteristic to this service.
237     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
238     *
239     * @param characteristic The characteristics to be added
240     * @return true, if the characteristic was added to the service
241     */
242    public boolean addCharacteristic(BluetoothGattCharacteristic characteristic) {
243        mCharacteristics.add(characteristic);
244        characteristic.setService(this);
245        return true;
246    }
247
248    /**
249     * Get characteristic by UUID and instanceId.
250     *
251     * @hide
252     */
253    /*package*/ BluetoothGattCharacteristic getCharacteristic(UUID uuid, int instanceId) {
254        for (BluetoothGattCharacteristic characteristic : mCharacteristics) {
255            if (uuid.equals(characteristic.getUuid())
256                    && characteristic.getInstanceId() == instanceId) {
257                return characteristic;
258            }
259        }
260        return null;
261    }
262
263    /**
264     * Force the instance ID.
265     *
266     * @hide
267     */
268    public void setInstanceId(int instanceId) {
269        mInstanceId = instanceId;
270    }
271
272    /**
273     * Get the handle count override (conformance testing.
274     *
275     * @hide
276     */
277    /*package*/ int getHandles() {
278        return mHandles;
279    }
280
281    /**
282     * Force the number of handles to reserve for this service.
283     * This is needed for conformance testing only.
284     *
285     * @hide
286     */
287    public void setHandles(int handles) {
288        mHandles = handles;
289    }
290
291    /**
292     * Add an included service to the internal map.
293     *
294     * @hide
295     */
296    public void addIncludedService(BluetoothGattService includedService) {
297        mIncludedServices.add(includedService);
298    }
299
300    /**
301     * Returns the UUID of this service
302     *
303     * @return UUID of this service
304     */
305    public UUID getUuid() {
306        return mUuid;
307    }
308
309    /**
310     * Returns the instance ID for this service
311     *
312     * <p>If a remote device offers multiple services with the same UUID
313     * (ex. multiple battery services for different batteries), the instance
314     * ID is used to distuinguish services.
315     *
316     * @return Instance ID of this service
317     */
318    public int getInstanceId() {
319        return mInstanceId;
320    }
321
322    /**
323     * Get the type of this service (primary/secondary)
324     */
325    public int getType() {
326        return mServiceType;
327    }
328
329    /**
330     * Get the list of included GATT services for this service.
331     *
332     * @return List of included services or empty list if no included services were discovered.
333     */
334    public List<BluetoothGattService> getIncludedServices() {
335        return mIncludedServices;
336    }
337
338    /**
339     * Returns a list of characteristics included in this service.
340     *
341     * @return Characteristics included in this service
342     */
343    public List<BluetoothGattCharacteristic> getCharacteristics() {
344        return mCharacteristics;
345    }
346
347    /**
348     * Returns a characteristic with a given UUID out of the list of
349     * characteristics offered by this service.
350     *
351     * <p>This is a convenience function to allow access to a given characteristic
352     * without enumerating over the list returned by {@link #getCharacteristics}
353     * manually.
354     *
355     * <p>If a remote service offers multiple characteristics with the same
356     * UUID, the first instance of a characteristic with the given UUID
357     * is returned.
358     *
359     * @return GATT characteristic object or null if no characteristic with the given UUID was
360     * found.
361     */
362    public BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
363        for (BluetoothGattCharacteristic characteristic : mCharacteristics) {
364            if (uuid.equals(characteristic.getUuid())) {
365                return characteristic;
366            }
367        }
368        return null;
369    }
370
371    /**
372     * Returns whether the uuid of the service should be advertised.
373     *
374     * @hide
375     */
376    public boolean isAdvertisePreferred() {
377        return mAdvertisePreferred;
378    }
379
380    /**
381     * Set whether the service uuid should be advertised.
382     *
383     * @hide
384     */
385    public void setAdvertisePreferred(boolean advertisePreferred) {
386        mAdvertisePreferred = advertisePreferred;
387    }
388}
389