AdapterService.java revision ff4f17bf64978d0738c66e1b6dd70be8664efc24
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 } 93 94 @Override 95 protected void finalize() throws Throwable { 96 mContext.unregisterReceiver(mReceiver); 97 try { 98 cleanupNative(); 99 } finally { 100 super.finalize(); 101 } 102 } 103 104 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 105 @Override 106 public void onReceive(Context context, Intent intent) { 107 if (intent == null) return; 108 109 String action = intent.getAction(); 110 if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 111 ContentResolver resolver = context.getContentResolver(); 112 // Query the airplane mode from Settings.System just to make sure that 113 // some random app is not sending this intent and disabling bluetooth 114 if (isAirplaneModeOn()) { 115 mAdapterStateMachine.sendMessage(AdapterState.AIRPLANE_MODE_ON); 116 } else { 117 mAdapterStateMachine.sendMessage(AdapterState.AIRPLANE_MODE_OFF); 118 } 119 } 120 } 121 }; 122 123 124 125 private void registerForAirplaneMode(IntentFilter filter) { 126 final ContentResolver resolver = mContext.getContentResolver(); 127 final String airplaneModeRadios = Settings.System.getString(resolver, 128 Settings.System.AIRPLANE_MODE_RADIOS); 129 final String toggleableRadios = Settings.System.getString(resolver, 130 Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 131 132 mIsAirplaneSensitive = airplaneModeRadios == null ? true : 133 airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH); 134 mIsAirplaneToggleable = toggleableRadios == null ? false : 135 toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH); 136 137 if (mIsAirplaneSensitive) { 138 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 139 } 140 } 141 142 /* Returns true if airplane mode is currently on */ 143 private final boolean isAirplaneModeOn() { 144 return Settings.System.getInt(mContext.getContentResolver(), 145 Settings.System.AIRPLANE_MODE_ON, 0) == 1; 146 } 147 148 /** 149 * Handlers for incoming service calls 150 */ 151 private final IBluetooth.Stub mBinder = new IBluetooth.Stub() { 152 public boolean isEnabled() { 153 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 154 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 155 } 156 157 public int getState() { 158 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 159 return mAdapterProperties.getState(); 160 } 161 162 public boolean enable() { 163 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 164 "Need BLUETOOTH ADMIN permission"); 165 mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON); 166 return true; 167 } 168 169 public boolean disable() { 170 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 171 "Need BLUETOOTH ADMIN permission"); 172 mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_OFF); 173 return true; 174 } 175 176 public String getAddress() { 177 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 178 String addrString = null; 179 byte[] address = mAdapterProperties.getAddress(); 180 return Utils.getAddressStringFromByte(address); 181 } 182 183 public ParcelUuid[] getUuids() { 184 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 185 return mAdapterProperties.getUuids(); 186 } 187 188 public String getName() { 189 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 190 "Need BLUETOOTH permission"); 191 return mAdapterProperties.getName(); 192 } 193 194 public boolean setName(String name) { 195 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 196 "Need BLUETOOTH ADMIN permission"); 197 return mAdapterProperties.setName(name); 198 } 199 200 public int getScanMode() { 201 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 202 return mAdapterProperties.getScanMode(); 203 } 204 205 public boolean setScanMode(int mode, int duration) { 206 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 207 setDiscoverableTimeout(duration); 208 209 int newMode = convertScanModeToHal(mode); 210 return mAdapterProperties.setScanMode(mode); 211 } 212 213 public int getDiscoverableTimeout() { 214 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 215 return mAdapterProperties.getDiscoverableTimeout(); 216 } 217 218 public boolean setDiscoverableTimeout(int timeout) { 219 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 220 return mAdapterProperties.setDiscoverableTimeout(timeout); 221 } 222 223 public boolean startDiscovery() { 224 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 225 "Need BLUETOOTH ADMIN permission"); 226 return startDiscoveryNative(); 227 } 228 229 public boolean cancelDiscovery() { 230 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 231 "Need BLUETOOTH ADMIN permission"); 232 return cancelDiscoveryNative(); 233 } 234 235 public boolean isDiscovering() { 236 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 237 return mAdapterProperties.isDiscovering(); 238 } 239 240 public BluetoothDevice[] getBondedDevices() { 241 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 242 debugLog("Get Bonded Devices being called"); 243 return mAdapterProperties.getBondedDevices(); 244 } 245 246 public int getAdapterConnectionState() { 247 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 248 return mAdapterProperties.getConnectionState(); 249 } 250 251 public int getProfileConnectionState(int profile) { 252 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 253 return mAdapterProperties.getProfileConnectionState(profile); 254 } 255 256 public boolean createBond(BluetoothDevice device) { 257 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 258 "Need BLUETOOTH ADMIN permission"); 259 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 260 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 261 return false; 262 } 263 264 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 265 msg.obj = device; 266 mBondStateMachine.sendMessage(msg); 267 return true; 268 } 269 270 public boolean cancelBondProcess(BluetoothDevice device) { 271 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 272 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 273 return cancelBondNative(addr); 274 } 275 276 public boolean removeBond(BluetoothDevice device) { 277 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 278 "Need BLUETOOTH ADMIN permission"); 279 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 280 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 281 return false; 282 } 283 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 284 msg.obj = device; 285 mBondStateMachine.sendMessage(msg); 286 return true; 287 } 288 289 public int getBondState(BluetoothDevice device) { 290 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 291 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 292 if (deviceProp == null) { 293 return BluetoothDevice.BOND_NONE; 294 } 295 return deviceProp.getBondState(); 296 } 297 298 public String getRemoteName(BluetoothDevice device) { 299 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 300 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 301 if (deviceProp == null) return null; 302 return deviceProp.getName(); 303 } 304 305 public String getRemoteAlias(BluetoothDevice device) { 306 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 307 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 308 if (deviceProp == null) return null; 309 return deviceProp.getAlias(); 310 } 311 312 public boolean setRemoteAlias(BluetoothDevice device, String name) { 313 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 314 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 315 if (deviceProp == null) return false; 316 deviceProp.setAlias(name); 317 return true; 318 } 319 320 public int getRemoteClass(BluetoothDevice device) { 321 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 322 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 323 if (deviceProp == null) return 0; 324 325 return deviceProp.getBluetoothClass(); 326 } 327 328 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 329 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 330 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 331 if (deviceProp == null) return null; 332 return deviceProp.getUuids(); 333 } 334 335 public boolean fetchRemoteUuids(BluetoothDevice device) { 336 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 337 mRemoteDevices.performSdp(device); 338 return true; 339 } 340 341 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 342 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 343 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 344 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 345 return false; 346 } 347 348 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 349 return pinReplyNative(addr, accept, len, pinCode); 350 } 351 352 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 353 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 354 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 355 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 356 return false; 357 } 358 359 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 360 return passkeyReplyNative(addr, accept, len, Utils.byteArrayToInt(passkey)); 361 } 362 363 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 364 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 365 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 366 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 367 return false; 368 } 369 370 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 371 return sspReplyNative(addr, accept); 372 } 373 374 public void sendConnectionStateChange(BluetoothDevice 375 device, int profile, int state, int prevState) { 376 // Since this is a binder call check if Bluetooth is on still 377 if (getState() == BluetoothAdapter.STATE_OFF) return; 378 379 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 380 381 } 382 383 }; 384 385 private int convertScanModeToHal(int mode) { 386 switch (mode) { 387 case BluetoothAdapter.SCAN_MODE_NONE: 388 return AbstractionLayer.BT_SCAN_MODE_NONE; 389 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 390 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 391 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 392 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 393 } 394 errorLog("Incorrect scan mode in convertScanModeToHal"); 395 return -1; 396 } 397 398 int convertScanModeFromHal(int mode) { 399 switch (mode) { 400 case AbstractionLayer.BT_SCAN_MODE_NONE: 401 return BluetoothAdapter.SCAN_MODE_NONE; 402 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 403 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 404 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 405 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 406 } 407 errorLog("Incorrect scan mode in convertScanModeFromHal"); 408 return -1; 409 } 410 411 private static void debugLog(String msg) { 412 Log.d(TAG, msg); 413 } 414 415 private static void errorLog(String msg) { 416 Log.e(TAG, msg); 417 } 418 419 void persistBluetoothSetting(boolean setOn) { 420 long origCallerIdentityToken = Binder.clearCallingIdentity(); 421 Settings.Secure.putInt(mContext.getContentResolver(), 422 Settings.Secure.BLUETOOTH_ON, 423 setOn ? 1 : 0); 424 Binder.restoreCallingIdentity(origCallerIdentityToken); 425 } 426 427 private boolean getBluetoothPersistedSetting() { 428 ContentResolver contentResolver = mContext.getContentResolver(); 429 return (Settings.Secure.getInt(contentResolver, 430 Settings.Secure.BLUETOOTH_ON, 0) > 0); 431 } 432 433 void onBluetoothEnabled() { 434 getAdapterPropertiesNative(); 435 } 436 437 void onBluetoothEnabledAdapterReady() { 438 mAdapterStateMachine.sendMessage(AdapterState.ENABLED_READY); 439 } 440 441 442 private native static void classInitNative(); 443 private native boolean initNative(); 444 private native void cleanupNative(); 445 /*package*/ native boolean enableNative(); 446 /*package*/ native boolean disableNative(); 447 /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val); 448 /*package*/ native boolean getAdapterPropertiesNative(); 449 /*package*/ native boolean getAdapterPropertyNative(int type); 450 /*package*/ native boolean setAdapterPropertyNative(int type); 451 /*package*/ native boolean 452 setDevicePropertyNative(byte[] address, int type, byte[] val); 453 /*package*/ native boolean getDevicePropertyNative(byte[] address, int type); 454 455 /*package*/ native boolean createBondNative(byte[] address); 456 /*package*/ native boolean removeBondNative(byte[] address); 457 /*package*/ native boolean cancelBondNative(byte[] address); 458 459 private native boolean startDiscoveryNative(); 460 private native boolean cancelDiscoveryNative(); 461 462 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 463 private native boolean passkeyReplyNative(byte[] address, boolean accept, int len, int passkey); 464 private native boolean sspReplyNative(byte[] address, boolean accept); 465} 466