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