1 /* 2 * Copyright (C) 2008 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 17 package android.bluetooth; 18 19 import android.annotation.Nullable; 20 import android.annotation.SystemApi; 21 import android.compat.annotation.UnsupportedAppUsage; 22 import android.os.Build; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 26 /** 27 * Represents a Bluetooth class, which describes general characteristics and capabilities of a 28 * device. For example, a Bluetooth class will specify the general device type such as a phone, a 29 * computer, or headset, and whether it's capable of services such as audio or telephony. 30 * 31 * <p>Every Bluetooth class is composed of zero or more service classes, and exactly one device 32 * class. The device class is further broken down into major and minor device class components. 33 * 34 * <p>{@link BluetoothClass} is useful as a hint to roughly describe a device (for example to show 35 * an icon in the UI), but does not reliably describe which Bluetooth profiles or services are 36 * actually supported by a device. Accurate service discovery is done through SDP requests, which 37 * are automatically performed when creating an RFCOMM socket with {@link 38 * BluetoothDevice#createRfcommSocketToServiceRecord} and {@link 39 * BluetoothAdapter#listenUsingRfcommWithServiceRecord} 40 * 41 * <p>Use {@link BluetoothDevice#getBluetoothClass} to retrieve the class for a remote device. 42 * <!-- 43 * The Bluetooth class is a 32 bit field. The format of these bits is defined at 44 * http://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm 45 * (login required). This class contains that 32 bit field, and provides 46 * constants and methods to determine which Service Class(es) and Device Class 47 * are encoded in that field. 48 * --> 49 */ 50 public final class BluetoothClass implements Parcelable { 51 /** 52 * Legacy error value. Applications should use null instead. 53 * 54 * @hide 55 */ 56 public static final int ERROR = 0xFF000000; 57 58 private final int mClass; 59 60 /** @hide */ 61 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) BluetoothClass(int classInt)62 public BluetoothClass(int classInt) { 63 mClass = classInt; 64 } 65 66 @Override equals(@ullable Object o)67 public boolean equals(@Nullable Object o) { 68 if (o instanceof BluetoothClass) { 69 return mClass == ((BluetoothClass) o).mClass; 70 } 71 return false; 72 } 73 74 @Override hashCode()75 public int hashCode() { 76 return mClass; 77 } 78 79 @Override toString()80 public String toString() { 81 return Integer.toHexString(mClass); 82 } 83 84 @Override describeContents()85 public int describeContents() { 86 return 0; 87 } 88 89 public static final @android.annotation.NonNull Parcelable.Creator<BluetoothClass> CREATOR = 90 new Parcelable.Creator<BluetoothClass>() { 91 public BluetoothClass createFromParcel(Parcel in) { 92 return new BluetoothClass(in.readInt()); 93 } 94 95 public BluetoothClass[] newArray(int size) { 96 return new BluetoothClass[size]; 97 } 98 }; 99 100 @Override writeToParcel(Parcel out, int flags)101 public void writeToParcel(Parcel out, int flags) { 102 out.writeInt(mClass); 103 } 104 105 /** 106 * Defines all service class constants. 107 * 108 * <p>Each {@link BluetoothClass} encodes zero or more service classes. 109 */ 110 public static final class Service { 111 private static final int BITMASK = 0xFFE000; 112 113 public static final int LIMITED_DISCOVERABILITY = 0x002000; 114 115 /** Represent devices LE audio service */ 116 public static final int LE_AUDIO = 0x004000; 117 118 public static final int POSITIONING = 0x010000; 119 public static final int NETWORKING = 0x020000; 120 public static final int RENDER = 0x040000; 121 public static final int CAPTURE = 0x080000; 122 public static final int OBJECT_TRANSFER = 0x100000; 123 public static final int AUDIO = 0x200000; 124 public static final int TELEPHONY = 0x400000; 125 public static final int INFORMATION = 0x800000; 126 } 127 128 /** 129 * Return true if the specified service class is supported by this {@link BluetoothClass}. 130 * 131 * <p>Valid service classes are the public constants in {@link BluetoothClass.Service}. For 132 * example, {@link BluetoothClass.Service#AUDIO}. 133 * 134 * @param service valid service class 135 * @return true if the service class is supported 136 */ hasService(int service)137 public boolean hasService(int service) { 138 return ((mClass & Service.BITMASK & service) != 0); 139 } 140 141 /** 142 * Defines all device class constants. 143 * 144 * <p>Each {@link BluetoothClass} encodes exactly one device class, with major and minor 145 * components. 146 * 147 * <p>The constants in {@link BluetoothClass.Device} represent a combination of major and minor 148 * device components (the complete device class). The constants in {@link 149 * BluetoothClass.Device.Major} represent only major device classes. 150 * 151 * <p>See {@link BluetoothClass.Service} for service class constants. 152 */ 153 public static class Device { 154 private static final int BITMASK = 0x1FFC; 155 156 /** 157 * Defines all major device class constants. 158 * 159 * <p>See {@link BluetoothClass.Device} for minor classes. 160 */ 161 public static class Major { 162 private static final int BITMASK = 0x1F00; 163 164 public static final int MISC = 0x0000; 165 public static final int COMPUTER = 0x0100; 166 public static final int PHONE = 0x0200; 167 public static final int NETWORKING = 0x0300; 168 public static final int AUDIO_VIDEO = 0x0400; 169 public static final int PERIPHERAL = 0x0500; 170 public static final int IMAGING = 0x0600; 171 public static final int WEARABLE = 0x0700; 172 public static final int TOY = 0x0800; 173 public static final int HEALTH = 0x0900; 174 public static final int UNCATEGORIZED = 0x1F00; 175 } 176 177 // Devices in the COMPUTER major class 178 public static final int COMPUTER_UNCATEGORIZED = 0x0100; 179 public static final int COMPUTER_DESKTOP = 0x0104; 180 public static final int COMPUTER_SERVER = 0x0108; 181 public static final int COMPUTER_LAPTOP = 0x010C; 182 public static final int COMPUTER_HANDHELD_PC_PDA = 0x0110; 183 public static final int COMPUTER_PALM_SIZE_PC_PDA = 0x0114; 184 public static final int COMPUTER_WEARABLE = 0x0118; 185 186 // Devices in the PHONE major class 187 public static final int PHONE_UNCATEGORIZED = 0x0200; 188 public static final int PHONE_CELLULAR = 0x0204; 189 public static final int PHONE_CORDLESS = 0x0208; 190 public static final int PHONE_SMART = 0x020C; 191 public static final int PHONE_MODEM_OR_GATEWAY = 0x0210; 192 public static final int PHONE_ISDN = 0x0214; 193 194 // Minor classes for the AUDIO_VIDEO major class 195 public static final int AUDIO_VIDEO_UNCATEGORIZED = 0x0400; 196 public static final int AUDIO_VIDEO_WEARABLE_HEADSET = 0x0404; 197 public static final int AUDIO_VIDEO_HANDSFREE = 0x0408; 198 // public static final int AUDIO_VIDEO_RESERVED = 0x040C; 199 public static final int AUDIO_VIDEO_MICROPHONE = 0x0410; 200 public static final int AUDIO_VIDEO_LOUDSPEAKER = 0x0414; 201 public static final int AUDIO_VIDEO_HEADPHONES = 0x0418; 202 public static final int AUDIO_VIDEO_PORTABLE_AUDIO = 0x041C; 203 public static final int AUDIO_VIDEO_CAR_AUDIO = 0x0420; 204 public static final int AUDIO_VIDEO_SET_TOP_BOX = 0x0424; 205 public static final int AUDIO_VIDEO_HIFI_AUDIO = 0x0428; 206 public static final int AUDIO_VIDEO_VCR = 0x042C; 207 public static final int AUDIO_VIDEO_VIDEO_CAMERA = 0x0430; 208 public static final int AUDIO_VIDEO_CAMCORDER = 0x0434; 209 public static final int AUDIO_VIDEO_VIDEO_MONITOR = 0x0438; 210 public static final int AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER = 0x043C; 211 public static final int AUDIO_VIDEO_VIDEO_CONFERENCING = 0x0440; 212 // public static final int AUDIO_VIDEO_RESERVED = 0x0444; 213 public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 0x0448; 214 215 // Devices in the WEARABLE major class 216 public static final int WEARABLE_UNCATEGORIZED = 0x0700; 217 public static final int WEARABLE_WRIST_WATCH = 0x0704; 218 public static final int WEARABLE_PAGER = 0x0708; 219 public static final int WEARABLE_JACKET = 0x070C; 220 public static final int WEARABLE_HELMET = 0x0710; 221 public static final int WEARABLE_GLASSES = 0x0714; 222 223 // Devices in the TOY major class 224 public static final int TOY_UNCATEGORIZED = 0x0800; 225 public static final int TOY_ROBOT = 0x0804; 226 public static final int TOY_VEHICLE = 0x0808; 227 public static final int TOY_DOLL_ACTION_FIGURE = 0x080C; 228 public static final int TOY_CONTROLLER = 0x0810; 229 public static final int TOY_GAME = 0x0814; 230 231 // Devices in the HEALTH major class 232 public static final int HEALTH_UNCATEGORIZED = 0x0900; 233 public static final int HEALTH_BLOOD_PRESSURE = 0x0904; 234 public static final int HEALTH_THERMOMETER = 0x0908; 235 public static final int HEALTH_WEIGHING = 0x090C; 236 public static final int HEALTH_GLUCOSE = 0x0910; 237 public static final int HEALTH_PULSE_OXIMETER = 0x0914; 238 public static final int HEALTH_PULSE_RATE = 0x0918; 239 public static final int HEALTH_DATA_DISPLAY = 0x091C; 240 241 // Devices in PERIPHERAL major class 242 public static final int PERIPHERAL_NON_KEYBOARD_NON_POINTING = 0x0500; 243 public static final int PERIPHERAL_KEYBOARD = 0x0540; 244 public static final int PERIPHERAL_POINTING = 0x0580; 245 public static final int PERIPHERAL_KEYBOARD_POINTING = 0x05C0; 246 } 247 248 /** 249 * Return the major device class component of this {@link BluetoothClass}. 250 * 251 * <p>Values returned from this function can be compared with the public constants in {@link 252 * BluetoothClass.Device.Major} to determine which major class is encoded in this Bluetooth 253 * class. 254 * 255 * @return major device class component 256 */ getMajorDeviceClass()257 public int getMajorDeviceClass() { 258 return (mClass & Device.Major.BITMASK); 259 } 260 261 /** 262 * Return the (major and minor) device class component of this {@link BluetoothClass}. 263 * 264 * <p>Values returned from this function can be compared with the public constants in {@link 265 * BluetoothClass.Device} to determine which device class is encoded in this Bluetooth class. 266 * 267 * @return device class component 268 */ getDeviceClass()269 public int getDeviceClass() { 270 return (mClass & Device.BITMASK); 271 } 272 273 /** 274 * Return the Bluetooth Class of Device (CoD) value including the {@link 275 * BluetoothClass.Service}, {@link BluetoothClass.Device.Major} and minor device fields. 276 * 277 * <p>This value is an integer representation of Bluetooth CoD as in Bluetooth specification. 278 * 279 * @see <a href="Bluetooth 280 * CoD">https://www.bluetooth.com/specifications/assigned-numbers/baseband</a> 281 * @hide 282 */ getClassOfDevice()283 public int getClassOfDevice() { 284 return mClass; 285 } 286 287 public static final int PROFILE_HEADSET = 0; 288 289 public static final int PROFILE_A2DP = 1; 290 291 /** @hide */ 292 @SystemApi public static final int PROFILE_OPP = 2; 293 294 public static final int PROFILE_HID = 3; 295 296 /** @hide */ 297 @SystemApi public static final int PROFILE_PANU = 4; 298 299 /** @hide */ 300 @SystemApi public static final int PROFILE_NAP = 5; 301 302 /** @hide */ 303 @SystemApi public static final int PROFILE_A2DP_SINK = 6; 304 305 /** 306 * Check class bits for possible bluetooth profile support. This is a simple heuristic that 307 * tries to guess if a device with the given class bits might support specified profile. It is 308 * not accurate for all devices. It tries to err on the side of false positives. 309 * 310 * @param profile the profile to be checked 311 * @return whether this device supports specified profile 312 */ doesClassMatch(int profile)313 public boolean doesClassMatch(int profile) { 314 if (profile == PROFILE_A2DP) { 315 if (hasService(Service.RENDER)) { 316 return true; 317 } 318 // By the A2DP spec, sinks must indicate the RENDER service. 319 // However we found some that do not (Chordette). So lets also 320 // match on some other class bits. 321 switch (getDeviceClass()) { 322 case Device.AUDIO_VIDEO_HIFI_AUDIO: 323 case Device.AUDIO_VIDEO_HEADPHONES: 324 case Device.AUDIO_VIDEO_LOUDSPEAKER: 325 case Device.AUDIO_VIDEO_CAR_AUDIO: 326 return true; 327 default: 328 return false; 329 } 330 } else if (profile == PROFILE_A2DP_SINK) { 331 if (hasService(Service.CAPTURE)) { 332 return true; 333 } 334 // By the A2DP spec, srcs must indicate the CAPTURE service. 335 // However if some device that do not, we try to 336 // match on some other class bits. 337 switch (getDeviceClass()) { 338 case Device.AUDIO_VIDEO_HIFI_AUDIO: 339 case Device.AUDIO_VIDEO_SET_TOP_BOX: 340 case Device.AUDIO_VIDEO_VCR: 341 return true; 342 default: 343 return false; 344 } 345 } else if (profile == PROFILE_HEADSET) { 346 // The render service class is required by the spec for HFP, so is a 347 // pretty good signal 348 if (hasService(Service.RENDER)) { 349 return true; 350 } 351 // Just in case they forgot the render service class 352 switch (getDeviceClass()) { 353 case Device.AUDIO_VIDEO_HANDSFREE: 354 case Device.AUDIO_VIDEO_WEARABLE_HEADSET: 355 case Device.AUDIO_VIDEO_CAR_AUDIO: 356 return true; 357 default: 358 return false; 359 } 360 } else if (profile == PROFILE_OPP) { 361 if (hasService(Service.OBJECT_TRANSFER)) { 362 return true; 363 } 364 365 switch (getDeviceClass()) { 366 case Device.COMPUTER_UNCATEGORIZED: 367 case Device.COMPUTER_DESKTOP: 368 case Device.COMPUTER_SERVER: 369 case Device.COMPUTER_LAPTOP: 370 case Device.COMPUTER_HANDHELD_PC_PDA: 371 case Device.COMPUTER_PALM_SIZE_PC_PDA: 372 case Device.COMPUTER_WEARABLE: 373 case Device.PHONE_UNCATEGORIZED: 374 case Device.PHONE_CELLULAR: 375 case Device.PHONE_CORDLESS: 376 case Device.PHONE_SMART: 377 case Device.PHONE_MODEM_OR_GATEWAY: 378 case Device.PHONE_ISDN: 379 return true; 380 default: 381 return false; 382 } 383 } else if (profile == PROFILE_HID) { 384 return getMajorDeviceClass() == Device.Major.PERIPHERAL; 385 } else if (profile == PROFILE_PANU || profile == PROFILE_NAP) { 386 // No good way to distinguish between the two, based on class bits. 387 if (hasService(Service.NETWORKING)) { 388 return true; 389 } 390 return getMajorDeviceClass() == Device.Major.NETWORKING; 391 } else { 392 return false; 393 } 394 } 395 } 396