AdapterService.java revision fba70fe2abecf70b9f9f7ee09a21cbfc6cb73998
1/* 2 * Copyright (C) 2012 Google Inc. 3 */ 4 5/** 6 * @hide 7 */ 8 9package com.android.bluetooth.btservice; 10 11import android.app.Application; 12import android.app.Service; 13import android.bluetooth.BluetoothAdapter; 14import android.bluetooth.BluetoothDevice; 15import android.bluetooth.BluetoothProfile; 16import android.bluetooth.IBluetooth; 17import android.content.BroadcastReceiver; 18import android.content.ContentResolver; 19import android.content.Context; 20import android.content.Intent; 21import android.content.IntentFilter; 22import android.os.Binder; 23import android.os.IBinder; 24import android.os.Message; 25import android.os.ParcelUuid; 26import android.os.RemoteException; 27import android.os.ServiceManager; 28import android.provider.Settings; 29import android.util.Log; 30import android.util.Pair; 31 32import com.android.bluetooth.Utils; 33import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 34 35import java.util.HashMap; 36import java.util.Set; 37 38public class AdapterService extends Application { 39 private static final String TAG = "BluetoothAdapterService"; 40 private static final boolean DBG = true; 41 42 static final String BLUETOOTH_ADMIN_PERM = 43 android.Manifest.permission.BLUETOOTH_ADMIN; 44 static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 45 46 private AdapterProperties mAdapterProperties; 47 private int mAdapterState; 48 private Context mContext; 49 private boolean mIsAirplaneSensitive; 50 private boolean mIsAirplaneToggleable; 51 private static AdapterService sAdapterService; 52 53 private BluetoothAdapter mAdapter; 54 private AdapterState mAdapterStateMachine; 55 private BondStateMachine mBondStateMachine; 56 private JniCallbacks mJniCallbacks; 57 58 59 private RemoteDevices mRemoteDevices; 60 static { 61 System.loadLibrary("bluetooth_jni"); 62 classInitNative(); 63 } 64 65 @Override 66 public void onCreate() { 67 super.onCreate(); 68 ServiceManager.addService(Context.BLUETOOTH_SERVICE, mBinder); 69 70 mAdapter = BluetoothAdapter.getDefaultAdapter(); 71 mContext = this; 72 sAdapterService = this; 73 74 IntentFilter filter = new IntentFilter(); 75 filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 76 registerForAirplaneMode(filter); 77 registerReceiver(mReceiver, filter); 78 79 mRemoteDevices = RemoteDevices.getInstance(this, mContext); 80 mAdapterProperties = AdapterProperties.getInstance(this, mContext); 81 mAdapterStateMachine = new AdapterState(this, mContext, mAdapterProperties); 82 mBondStateMachine = new BondStateMachine(this, mContext, mAdapterProperties); 83 mJniCallbacks = JniCallbacks.getInstance(mRemoteDevices, mAdapterProperties, 84 mAdapterStateMachine, mBondStateMachine); 85 86 87 initNative(); 88 mAdapterStateMachine.start(); 89 mBondStateMachine.start(); 90 // TODO(BT): Start other profile services. 91 // startService(); 92 //TODO(BT): Remove this when BT is no longer a persitent process. 93 int bluetoothOn = Settings.Secure.getInt(mContext.getContentResolver(), 94 Settings.Secure.BLUETOOTH_ON, 0); 95 if (!isAirplaneModeOn() && bluetoothOn != 0) mAdapter.enable(); 96 } 97 98 @Override 99 protected void finalize() throws Throwable { 100 mContext.unregisterReceiver(mReceiver); 101 try { 102 cleanupNative(); 103 } finally { 104 super.finalize(); 105 } 106 } 107 108 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 109 @Override 110 public void onReceive(Context context, Intent intent) { 111 if (intent == null) return; 112 113 String action = intent.getAction(); 114 if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 115 ContentResolver resolver = context.getContentResolver(); 116 // Query the airplane mode from Settings.System just to make sure that 117 // some random app is not sending this intent and disabling bluetooth 118 if (isAirplaneModeOn()) { 119 mAdapterStateMachine.sendMessage(AdapterState.AIRPLANE_MODE_ON); 120 } else { 121 mAdapterStateMachine.sendMessage(AdapterState.AIRPLANE_MODE_OFF); 122 } 123 } 124 } 125 }; 126 127 128 129 private void registerForAirplaneMode(IntentFilter filter) { 130 final ContentResolver resolver = mContext.getContentResolver(); 131 final String airplaneModeRadios = Settings.System.getString(resolver, 132 Settings.System.AIRPLANE_MODE_RADIOS); 133 final String toggleableRadios = Settings.System.getString(resolver, 134 Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 135 136 mIsAirplaneSensitive = airplaneModeRadios == null ? true : 137 airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH); 138 mIsAirplaneToggleable = toggleableRadios == null ? false : 139 toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH); 140 141 if (mIsAirplaneSensitive) { 142 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 143 } 144 } 145 146 /* Returns true if airplane mode is currently on */ 147 private final boolean isAirplaneModeOn() { 148 return Settings.System.getInt(mContext.getContentResolver(), 149 Settings.System.AIRPLANE_MODE_ON, 0) == 1; 150 } 151 152 /** 153 * Handlers for incoming service calls 154 */ 155 private final IBluetooth.Stub mBinder = new IBluetooth.Stub() { 156 public boolean isEnabled() { 157 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 158 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 159 } 160 161 public int getState() { 162 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 163 return mAdapterProperties.getState(); 164 } 165 166 public boolean enable() { 167 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 168 "Need BLUETOOTH ADMIN permission"); 169 // Persist the setting 170 Message m = 171 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 172 m.arg1 = 1; 173 mAdapterStateMachine.sendMessage(m); 174 return true; 175 } 176 177 public boolean disable(boolean persist) { 178 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 179 "Need BLUETOOTH ADMIN permission"); 180 int val = (persist ? 1 : 0); 181 Message m = 182 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 183 m.arg1 = val; 184 mAdapterStateMachine.sendMessage(m); 185 return true; 186 } 187 188 public String getAddress() { 189 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 190 String addrString = null; 191 byte[] address = mAdapterProperties.getAddress(); 192 return Utils.getAddressStringFromByte(address); 193 } 194 195 public ParcelUuid[] getUuids() { 196 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 197 return mAdapterProperties.getUuids(); 198 } 199 200 public String getName() { 201 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 202 "Need BLUETOOTH permission"); 203 return mAdapterProperties.getName(); 204 } 205 206 public boolean setName(String name) { 207 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 208 "Need BLUETOOTH ADMIN permission"); 209 return mAdapterProperties.setName(name); 210 } 211 212 public int getScanMode() { 213 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 214 return mAdapterProperties.getScanMode(); 215 } 216 217 public boolean setScanMode(int mode, int duration) { 218 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 219 setDiscoverableTimeout(duration); 220 221 int newMode = convertScanModeToHal(mode); 222 return mAdapterProperties.setScanMode(newMode); 223 } 224 225 public int getDiscoverableTimeout() { 226 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 227 return mAdapterProperties.getDiscoverableTimeout(); 228 } 229 230 public boolean setDiscoverableTimeout(int timeout) { 231 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 232 return mAdapterProperties.setDiscoverableTimeout(timeout); 233 } 234 235 public boolean startDiscovery() { 236 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 237 "Need BLUETOOTH ADMIN permission"); 238 return startDiscoveryNative(); 239 } 240 241 public boolean cancelDiscovery() { 242 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 243 "Need BLUETOOTH ADMIN permission"); 244 return cancelDiscoveryNative(); 245 } 246 247 public boolean isDiscovering() { 248 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 249 return mAdapterProperties.isDiscovering(); 250 } 251 252 public BluetoothDevice[] getBondedDevices() { 253 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 254 debugLog("Get Bonded Devices being called"); 255 return mAdapterProperties.getBondedDevices(); 256 } 257 258 public int getAdapterConnectionState() { 259 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 260 return mAdapterProperties.getConnectionState(); 261 } 262 263 public int getProfileConnectionState(int profile) { 264 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 265 return mAdapterProperties.getProfileConnectionState(profile); 266 } 267 268 public boolean createBond(BluetoothDevice device) { 269 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 270 "Need BLUETOOTH ADMIN permission"); 271 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 272 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 273 return false; 274 } 275 276 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 277 msg.obj = device; 278 mBondStateMachine.sendMessage(msg); 279 return true; 280 } 281 282 public boolean cancelBondProcess(BluetoothDevice device) { 283 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 284 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 285 return cancelBondNative(addr); 286 } 287 288 public boolean removeBond(BluetoothDevice device) { 289 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 290 "Need BLUETOOTH ADMIN permission"); 291 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 292 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 293 return false; 294 } 295 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 296 msg.obj = device; 297 mBondStateMachine.sendMessage(msg); 298 return true; 299 } 300 301 public int getBondState(BluetoothDevice device) { 302 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 303 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 304 if (deviceProp == null) { 305 return BluetoothDevice.BOND_NONE; 306 } 307 return deviceProp.getBondState(); 308 } 309 310 public String getRemoteName(BluetoothDevice device) { 311 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 312 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 313 if (deviceProp == null) return null; 314 return deviceProp.getName(); 315 } 316 317 public String getRemoteAlias(BluetoothDevice device) { 318 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 319 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 320 if (deviceProp == null) return null; 321 return deviceProp.getAlias(); 322 } 323 324 public boolean setRemoteAlias(BluetoothDevice device, String name) { 325 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 326 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 327 if (deviceProp == null) return false; 328 deviceProp.setAlias(name); 329 return true; 330 } 331 332 public int getRemoteClass(BluetoothDevice device) { 333 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 334 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 335 if (deviceProp == null) return 0; 336 337 return deviceProp.getBluetoothClass(); 338 } 339 340 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 341 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 342 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 343 if (deviceProp == null) return null; 344 return deviceProp.getUuids(); 345 } 346 347 public boolean fetchRemoteUuids(BluetoothDevice device) { 348 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 349 mRemoteDevices.performSdp(device); 350 return true; 351 } 352 353 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 354 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 355 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 356 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 357 return false; 358 } 359 360 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 361 return pinReplyNative(addr, accept, len, pinCode); 362 } 363 364 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 365 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 366 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 367 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 368 return false; 369 } 370 371 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 372 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept, 373 Utils.byteArrayToInt(passkey)); 374 } 375 376 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 377 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 378 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 379 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 380 return false; 381 } 382 383 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 384 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 385 accept, 0); 386 } 387 388 public void sendConnectionStateChange(BluetoothDevice 389 device, int profile, int state, int prevState) { 390 // Since this is a binder call check if Bluetooth is on still 391 if (getState() == BluetoothAdapter.STATE_OFF) return; 392 393 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 394 395 } 396 397 }; 398 399 private int convertScanModeToHal(int mode) { 400 switch (mode) { 401 case BluetoothAdapter.SCAN_MODE_NONE: 402 return AbstractionLayer.BT_SCAN_MODE_NONE; 403 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 404 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 405 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 406 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 407 } 408 errorLog("Incorrect scan mode in convertScanModeToHal"); 409 return -1; 410 } 411 412 int convertScanModeFromHal(int mode) { 413 switch (mode) { 414 case AbstractionLayer.BT_SCAN_MODE_NONE: 415 return BluetoothAdapter.SCAN_MODE_NONE; 416 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 417 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 418 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 419 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 420 } 421 errorLog("Incorrect scan mode in convertScanModeFromHal"); 422 return -1; 423 } 424 425 private static void debugLog(String msg) { 426 Log.d(TAG, msg); 427 } 428 429 private static void errorLog(String msg) { 430 Log.e(TAG, msg); 431 } 432 433 void persistBluetoothSetting(boolean setOn) { 434 long origCallerIdentityToken = Binder.clearCallingIdentity(); 435 Settings.Secure.putInt(mContext.getContentResolver(), 436 Settings.Secure.BLUETOOTH_ON, 437 setOn ? 1 : 0); 438 Binder.restoreCallingIdentity(origCallerIdentityToken); 439 } 440 441 private boolean getBluetoothPersistedSetting() { 442 ContentResolver contentResolver = mContext.getContentResolver(); 443 return (Settings.Secure.getInt(contentResolver, 444 Settings.Secure.BLUETOOTH_ON, 0) > 0); 445 } 446 447 void onBluetoothEnabled() { 448 getAdapterPropertiesNative(); 449 } 450 451 void onBluetoothEnabledAdapterReady() { 452 mAdapterStateMachine.sendMessage(AdapterState.ENABLED_READY); 453 } 454 455 456 private native static void classInitNative(); 457 private native boolean initNative(); 458 private native void cleanupNative(); 459 /*package*/ native boolean enableNative(); 460 /*package*/ native boolean disableNative(); 461 /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val); 462 /*package*/ native boolean getAdapterPropertiesNative(); 463 /*package*/ native boolean getAdapterPropertyNative(int type); 464 /*package*/ native boolean setAdapterPropertyNative(int type); 465 /*package*/ native boolean 466 setDevicePropertyNative(byte[] address, int type, byte[] val); 467 /*package*/ native boolean getDevicePropertyNative(byte[] address, int type); 468 469 /*package*/ native boolean createBondNative(byte[] address); 470 /*package*/ native boolean removeBondNative(byte[] address); 471 /*package*/ native boolean cancelBondNative(byte[] address); 472 473 private native boolean startDiscoveryNative(); 474 private native boolean cancelDiscoveryNative(); 475 476 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 477 private native boolean sspReplyNative(byte[] address, int type, boolean 478 accept, int passkey); 479} 480