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