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