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