RemoteDevices.java revision 8826b161f865350f306e8f287aaca615e2f1e4a3
1/* 2 * Copyright (C) 2012 Google Inc. 3 */ 4 5package com.android.bluetooth.btservice; 6 7import android.bluetooth.BluetoothAdapter; 8import android.bluetooth.BluetoothClass; 9import android.bluetooth.BluetoothDevice; 10import android.content.Context; 11import android.content.Intent; 12import android.os.Handler; 13import android.os.Message; 14import android.os.ParcelUuid; 15import android.util.Log; 16 17import com.android.bluetooth.Utils; 18import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 19 20import java.util.ArrayList; 21import java.util.HashMap; 22import java.util.LinkedList; 23 24 25final class RemoteDevices { 26 private static final boolean DBG = true; 27 private static final String TAG = "BluetoothRemoteDevices"; 28 29 private static Context mContext; 30 private static BluetoothAdapter mAdapter; 31 private static AdapterService mAdapterService; 32 private static ArrayList<BluetoothDevice> mSdpTracker; 33 34 private Object mObject = new Object(); 35 36 private static final int UUID_INTENT_DELAY = 6000; 37 private static final int MESSAGE_UUID_INTENT = 1; 38 39 private HashMap<BluetoothDevice, DeviceProperties> mDevices; 40 private static RemoteDevices sInstance; 41 42 private RemoteDevices(AdapterService service, Context context) { 43 mAdapter = BluetoothAdapter.getDefaultAdapter(); 44 mAdapterService = service; 45 mSdpTracker = new ArrayList<BluetoothDevice>(); 46 mDevices = new HashMap<BluetoothDevice, DeviceProperties>(); 47 mContext = context; 48 } 49 50 static synchronized RemoteDevices getInstance(AdapterService service, Context context) { 51 if (sInstance == null) sInstance = new RemoteDevices(service, context); 52 return sInstance; 53 } 54 55 public Object Clone() throws CloneNotSupportedException { 56 throw new CloneNotSupportedException(); 57 } 58 59 DeviceProperties getDeviceProperties(BluetoothDevice device) { 60 synchronized (mDevices) { 61 return mDevices.get(device); 62 } 63 } 64 65 BluetoothDevice getDevice(byte[] address) { 66 for (BluetoothDevice dev : mDevices.keySet()) { 67 if (dev.getAddress().equals(Utils.getAddressStringFromByte(address))) { 68 return dev; 69 } 70 } 71 return null; 72 } 73 74 DeviceProperties addDeviceProperties(byte[] address) { 75 synchronized (mDevices) { 76 DeviceProperties prop = new DeviceProperties(); 77 BluetoothDevice device = 78 mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address)); 79 mDevices.put(device, prop); 80 return prop; 81 } 82 } 83 84 class DeviceProperties { 85 private String mName; 86 private byte[] mAddress; 87 private int mBluetoothClass; 88 private short mRssi; 89 private ParcelUuid[] mUuids; 90 private int mDeviceType; 91 private String mAlias; 92 private int mBondState; 93 94 DeviceProperties() { 95 mBondState = BluetoothDevice.BOND_NONE; 96 } 97 98 /** 99 * @return the mName 100 */ 101 String getName() { 102 synchronized (mObject) { 103 return mName; 104 } 105 } 106 107 /** 108 * @return the mClass 109 */ 110 int getBluetoothClass() { 111 synchronized (mObject) { 112 return mBluetoothClass; 113 } 114 } 115 116 /** 117 * @return the mUuids 118 */ 119 ParcelUuid[] getUuids() { 120 synchronized (mObject) { 121 return mUuids; 122 } 123 } 124 125 /** 126 * @return the mAddress 127 */ 128 byte[] getAddress() { 129 synchronized (mObject) { 130 return mAddress; 131 } 132 } 133 134 /** 135 * @return mRssi 136 */ 137 short getRssi() { 138 synchronized (mObject) { 139 return mRssi; 140 } 141 } 142 143 /** 144 * 145 * @return mDeviceType 146 */ 147 int getDeviceType() { 148 synchronized (mObject) { 149 return mDeviceType; 150 } 151 } 152 153 /** 154 * @return the mAlias 155 */ 156 String getAlias() { 157 synchronized (mObject) { 158 return mAlias; 159 } 160 } 161 162 /** 163 * @param mAlias the mAlias to set 164 */ 165 void setAlias(String mAlias) { 166 synchronized (mObject) { 167 mAdapterService.setDevicePropertyNative(mAddress, 168 AbstractionLayer.BT_PROPERTY_REMOTE_FRIENDLY_NAME, mAlias.getBytes()); 169 } 170 } 171 172 /** 173 * @param mBondState the mBondState to set 174 */ 175 void setBondState(int mBondState) { 176 synchronized (mObject) { 177 this.mBondState = mBondState; 178 } 179 } 180 181 /** 182 * @return the mBondState 183 */ 184 int getBondState() { 185 synchronized (mObject) { 186 return mBondState; 187 } 188 } 189 } 190 191 192 private void sendUuidIntent(BluetoothDevice device) { 193 DeviceProperties prop = getDeviceProperties(device); 194 Intent intent = new Intent(BluetoothDevice.ACTION_UUID); 195 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 196 intent.putExtra(BluetoothDevice.EXTRA_UUID, prop.mUuids); 197 mContext.sendBroadcast(intent, AdapterService.BLUETOOTH_ADMIN_PERM); 198 } 199 200 void devicePropertyChangedCallback(byte[] address, int[] types, byte[][] values) { 201 Intent intent; 202 byte[] val; 203 int type; 204 BluetoothDevice bdDevice = getDevice(address); 205 DeviceProperties device; 206 if (bdDevice == null) { 207 device = addDeviceProperties(address); 208 bdDevice = getDevice(address); 209 } else { 210 device = getDeviceProperties(bdDevice); 211 } 212 213 for (int j = 0; j < types.length; j++) { 214 type = types[j]; 215 val = values[j]; 216 synchronized(mObject) { 217 switch (type) { 218 case AbstractionLayer.BT_PROPERTY_BDNAME: 219 device.mName = new String(val); 220 intent = new Intent(BluetoothDevice.ACTION_NAME_CHANGED); 221 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, bdDevice); 222 intent.putExtra(BluetoothDevice.EXTRA_NAME, device.mName); 223 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 224 mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM); 225 debugLog("Remote Device ame is: " + device.mName); 226 break; 227 case AbstractionLayer.BT_PROPERTY_REMOTE_FRIENDLY_NAME: 228 // TODO(BT) is null device.mAlias a valid senario? 229 if (device.mAlias != null) { 230 System.arraycopy(val, 0, device.mAlias, 0, val.length); 231 } 232 break; 233 case AbstractionLayer.BT_PROPERTY_BDADDR: 234 device.mAddress = val; 235 debugLog("Remote Address is:" + Utils.getAddressStringFromByte(val)); 236 break; 237 case AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE: 238 device.mBluetoothClass = Utils.byteArrayToInt(val); 239 intent = new Intent(BluetoothDevice.ACTION_CLASS_CHANGED); 240 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, bdDevice); 241 intent.putExtra(BluetoothDevice.EXTRA_CLASS, 242 new BluetoothClass(device.mBluetoothClass)); 243 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 244 mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM); 245 debugLog("Remote class is:" + device.mBluetoothClass); 246 break; 247 case AbstractionLayer.BT_PROPERTY_UUIDS: 248 int numUuids = val.length/AbstractionLayer.BT_UUID_SIZE; 249 device.mUuids = Utils.byteArrayToUuid(val); 250 sendUuidIntent(bdDevice); 251 break; 252 case AbstractionLayer.BT_PROPERTY_TYPE_OF_DEVICE: 253 device.mDeviceType = Utils.byteArrayToInt(val); 254 break; 255 case AbstractionLayer.BT_PROPERTY_REMOTE_RSSI: 256 device.mRssi = Utils.byteArrayToShort(val); 257 break; 258 } 259 } 260 } 261 } 262 263 void deviceFoundCallback(byte[] address) { 264 // The device properties are already registered - we can send the intent 265 // now 266 BluetoothDevice device = getDevice(address); 267 debugLog("deviceFoundCallback: Remote Address is:" + device); 268 DeviceProperties deviceProp = getDeviceProperties(device); 269 if (deviceProp == null) { 270 errorLog("Device Properties is null for Device:" + device); 271 return; 272 } 273 274 Intent intent = new Intent(BluetoothDevice.ACTION_FOUND); 275 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 276 intent.putExtra(BluetoothDevice.EXTRA_CLASS, 277 new BluetoothClass(Integer.valueOf(deviceProp.mBluetoothClass))); 278 intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi); 279 intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName); 280 281 mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM); 282 } 283 284 void pinRequestCallback(byte[] address, byte[] name, int cod) { 285 //TODO(BT): Get wakelock and update name and cod 286 BluetoothDevice bdDevice = getDevice(address); 287 if (bdDevice == null) { 288 addDeviceProperties(address); 289 } 290 infoLog("pinRequestCallback: " + address + " name:" + name + " cod:" + 291 cod); 292 Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); 293 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, getDevice(address)); 294 intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, 295 BluetoothDevice.PAIRING_VARIANT_PIN); 296 mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_ADMIN_PERM); 297 return; 298 } 299 300 void sspRequestCallback(byte[] address, byte[] name, int cod, int pairingVariant, 301 int passkey) { 302 //TODO(BT): Get wakelock and update name and cod 303 BluetoothDevice bdDevice = getDevice(address); 304 if (bdDevice == null) { 305 addDeviceProperties(address); 306 } 307 308 infoLog("sspRequestCallback: " + address + " name: " + name + " cod: " + 309 cod + " pairingVariant " + pairingVariant + " passkey: " + passkey); 310 int variant; 311 boolean displayPasskey = false; 312 if (pairingVariant == AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION) { 313 variant = BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION; 314 displayPasskey = true; 315 } else if (pairingVariant == AbstractionLayer.BT_SSP_VARIANT_CONSENT) { 316 variant = BluetoothDevice.PAIRING_VARIANT_CONSENT; 317 } else if (pairingVariant == AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY) { 318 variant = BluetoothDevice.PAIRING_VARIANT_PASSKEY; 319 } else if (pairingVariant == AbstractionLayer.BT_SSP_VARIANT_PASSKEY_NOTIFICATION) { 320 variant = BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY; 321 displayPasskey = true; 322 } else { 323 errorLog("SSP Pairing variant not present"); 324 return; 325 } 326 BluetoothDevice device = getDevice(address); 327 if (device == null) { 328 warnLog("Device is not known for:" + Utils.getAddressStringFromByte(address)); 329 addDeviceProperties(address); 330 device = getDevice(address); 331 } 332 Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); 333 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 334 if (displayPasskey) { 335 intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, passkey); 336 } 337 intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, variant); 338 mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_ADMIN_PERM); 339 } 340 341 342 void performSdp(BluetoothDevice device) { 343 if (mSdpTracker.contains(device)) return; 344 mSdpTracker.add(device); 345 346 Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT); 347 message.obj = device; 348 mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY); 349 350 //TODO(BT) 351 //mAdapterService.performSdpNative(device.mAddress); 352 } 353 354 private final Handler mHandler = new Handler() { 355 @Override 356 public void handleMessage(Message msg) { 357 switch (msg.what) { 358 case MESSAGE_UUID_INTENT: 359 BluetoothDevice device = (BluetoothDevice)msg.obj; 360 if (device != null) { 361 sendUuidIntent(device); 362 } 363 break; 364 } 365 } 366 }; 367 368 private void errorLog(String msg) { 369 Log.e(TAG, msg); 370 } 371 372 private void debugLog(String msg) { 373 if (DBG) Log.e(TAG, msg); 374 } 375 376 private void infoLog(String msg) { 377 if (DBG) Log.i(TAG, msg); 378 } 379 380 private void warnLog(String msg) { 381 Log.w(TAG, msg); 382 } 383} 384