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<>(); 102 mIncludedServices = new ArrayList<>(); 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<>(); 117 mIncludedServices = new ArrayList<>(); 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<>(); 131 mIncludedServices = new ArrayList<>(); 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 (new ParcelUuid(mUuid)).writeToParcel(out, flags); 142 out.writeInt(mInstanceId); 143 out.writeInt(mServiceType); 144 out.writeTypedList(mCharacteristics); 145 146 ArrayList<BluetoothGattIncludedService> includedServices = 147 new ArrayList<>(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.CREATOR.createFromParcel(in).getUuid(); 168 mInstanceId = in.readInt(); 169 mServiceType = in.readInt(); 170 171 mCharacteristics = in.createTypedArrayList(BluetoothGattCharacteristic.CREATOR); 172 for (BluetoothGattCharacteristic chrc : mCharacteristics) { 173 chrc.setService(this); 174 } 175 176 mIncludedServices = new ArrayList<>(); 177 178 List<BluetoothGattIncludedService> inclSvcs = 179 in.createTypedArrayList(BluetoothGattIncludedService.CREATOR); 180 for (BluetoothGattIncludedService isvc : inclSvcs) { 181 mIncludedServices.add( 182 new BluetoothGattService( 183 null, isvc.getUuid(), isvc.getInstanceId(), isvc.getType())); 184 } 185 } 186 187 /** 188 * Returns the device associated with this service. 189 * 190 * @hide 191 */ getDevice()192 /*package*/ BluetoothDevice getDevice() { 193 return mDevice; 194 } 195 196 /** 197 * Returns the device associated with this service. 198 * 199 * @hide 200 */ setDevice(BluetoothDevice device)201 /*package*/ void setDevice(BluetoothDevice device) { 202 mDevice = device; 203 } 204 205 /** 206 * Add an included service to this service. 207 * 208 * @param service The service to be added 209 * @return true, if the included service was added to the service 210 */ 211 @RequiresLegacyBluetoothPermission addService(BluetoothGattService service)212 public boolean addService(BluetoothGattService service) { 213 mIncludedServices.add(service); 214 return true; 215 } 216 217 /** 218 * Add a characteristic to this service. 219 * 220 * @param characteristic The characteristics to be added 221 * @return true, if the characteristic was added to the service 222 */ 223 @RequiresLegacyBluetoothPermission addCharacteristic(BluetoothGattCharacteristic characteristic)224 public boolean addCharacteristic(BluetoothGattCharacteristic characteristic) { 225 mCharacteristics.add(characteristic); 226 characteristic.setService(this); 227 return true; 228 } 229 230 /** 231 * Get characteristic by UUID and instanceId. 232 * 233 * @hide 234 */ getCharacteristic(UUID uuid, int instanceId)235 /*package*/ BluetoothGattCharacteristic getCharacteristic(UUID uuid, int instanceId) { 236 for (BluetoothGattCharacteristic characteristic : mCharacteristics) { 237 if (uuid.equals(characteristic.getUuid()) 238 && characteristic.getInstanceId() == instanceId) { 239 return characteristic; 240 } 241 } 242 return null; 243 } 244 245 /** 246 * Force the instance ID. 247 * 248 * @hide 249 */ 250 @UnsupportedAppUsage setInstanceId(int instanceId)251 public void setInstanceId(int instanceId) { 252 mInstanceId = instanceId; 253 } 254 255 /** 256 * Get the handle count override (conformance testing. 257 * 258 * @hide 259 */ getHandles()260 /*package*/ int getHandles() { 261 return mHandles; 262 } 263 264 /** 265 * Force the number of handles to reserve for this service. This is needed for conformance 266 * testing only. 267 * 268 * @hide 269 */ setHandles(int handles)270 public void setHandles(int handles) { 271 mHandles = handles; 272 } 273 274 /** 275 * Add an included service to the internal map. 276 * 277 * @hide 278 */ addIncludedService(BluetoothGattService includedService)279 public void addIncludedService(BluetoothGattService includedService) { 280 mIncludedServices.add(includedService); 281 } 282 283 /** 284 * Returns the UUID of this service 285 * 286 * @return UUID of this service 287 */ getUuid()288 public UUID getUuid() { 289 return mUuid; 290 } 291 292 /** 293 * Returns the instance ID for this service 294 * 295 * <p>If a remote device offers multiple services with the same UUID (ex. multiple battery 296 * services for different batteries), the instance ID is used to distinguish services. 297 * 298 * @return Instance ID of this service 299 */ getInstanceId()300 public int getInstanceId() { 301 return mInstanceId; 302 } 303 304 /** Get the type of this service (primary/secondary) */ getType()305 public int getType() { 306 return mServiceType; 307 } 308 309 /** 310 * Get the list of included GATT services for this service. 311 * 312 * @return List of included services or empty list if no included services were discovered. 313 */ getIncludedServices()314 public List<BluetoothGattService> getIncludedServices() { 315 return mIncludedServices; 316 } 317 318 /** 319 * Returns a list of characteristics included in this service. 320 * 321 * @return Characteristics included in this service 322 */ getCharacteristics()323 public List<BluetoothGattCharacteristic> getCharacteristics() { 324 return mCharacteristics; 325 } 326 327 /** 328 * Returns a characteristic with a given UUID out of the list of characteristics offered by this 329 * service. 330 * 331 * <p>This is a convenience function to allow access to a given characteristic without 332 * enumerating over the list returned by {@link #getCharacteristics} manually. 333 * 334 * <p>If a remote service offers multiple characteristics with the same UUID, the first instance 335 * of a characteristic with the given UUID is returned. 336 * 337 * @return GATT characteristic object or null if no characteristic with the given UUID was 338 * found. 339 */ getCharacteristic(UUID uuid)340 public BluetoothGattCharacteristic getCharacteristic(UUID uuid) { 341 for (BluetoothGattCharacteristic characteristic : mCharacteristics) { 342 if (uuid.equals(characteristic.getUuid())) { 343 return characteristic; 344 } 345 } 346 return null; 347 } 348 349 /** 350 * Returns whether the uuid of the service should be advertised. 351 * 352 * @hide 353 */ isAdvertisePreferred()354 public boolean isAdvertisePreferred() { 355 return mAdvertisePreferred; 356 } 357 358 /** 359 * Set whether the service uuid should be advertised. 360 * 361 * @hide 362 */ 363 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setAdvertisePreferred(boolean advertisePreferred)364 public void setAdvertisePreferred(boolean advertisePreferred) { 365 mAdvertisePreferred = advertisePreferred; 366 } 367 } 368