AdapterService.java revision 31ba132491053bc86d419a7d51fc04af3299c076
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.bluetooth.IBluetoothManager; 18import android.bluetooth.IBluetoothManagerCallback; 19import android.content.BroadcastReceiver; 20import android.content.ContentResolver; 21import android.content.Context; 22import android.content.Intent; 23import android.content.IntentFilter; 24import android.os.Binder; 25import android.os.Bundle; 26import android.os.Handler; 27import android.os.IBinder; 28import android.os.Message; 29import android.os.ParcelFileDescriptor; 30import android.os.ParcelUuid; 31import android.os.RemoteException; 32import android.provider.Settings; 33import android.util.Log; 34import android.util.Pair; 35import com.android.bluetooth.a2dp.A2dpService; 36import com.android.bluetooth.hid.HidService; 37import com.android.bluetooth.hfp.HeadsetService; 38import com.android.bluetooth.hdp.HealthService; 39import com.android.bluetooth.pan.PanService; 40import com.android.bluetooth.Utils; 41import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 42import java.io.FileDescriptor; 43import java.io.IOException; 44import java.util.HashMap; 45import java.util.Set; 46import java.util.Map; 47import java.util.Iterator; 48import java.util.Map.Entry; 49import android.content.pm.PackageManager; 50import android.os.ServiceManager; 51 52public class AdapterService extends Service { 53 private static final String TAG = "BluetoothAdapterService"; 54 private static final boolean DBG = true; 55 56 /** 57 * List of profile services to support.Comment out to disable a profile 58 * Profiles started in order of appearance 59 */ 60 @SuppressWarnings("rawtypes") 61 private static final Class[] SUPPORTED_PROFILE_SERVICES = { 62 HeadsetService.class, 63 A2dpService.class, 64 HidService.class, 65 HealthService.class, 66 PanService.class 67 }; 68 69 public static final String ACTION_LOAD_ADAPTER_PROPERTIES="com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES"; 70 public static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED"; 71 public static final String EXTRA_ACTION="action"; 72 73 static final String BLUETOOTH_ADMIN_PERM = 74 android.Manifest.permission.BLUETOOTH_ADMIN; 75 static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 76 77 private static final int ADAPTER_SERVICE_TYPE=Service.START_STICKY; 78 79 static { 80 classInitNative(); 81 } 82 83 private static AdapterService sAdapterService; 84 public static AdapterService getAdapterService(){ 85 return sAdapterService; 86 } 87 88 private IBluetoothManager mBluetoothManager; 89 private IBluetooth mBluetoothService; 90 private AdapterProperties mAdapterProperties; 91 private int mAdapterState; 92 private Context mContext; 93 94 private AdapterState mAdapterStateMachine; 95 private BondStateMachine mBondStateMachine; 96 private JniCallbacks mJniCallbacks; 97 private RemoteDevices mRemoteDevices; 98 private boolean mProfilesStarted; 99 private boolean mNativeAvailable; 100 private HashMap<String,Integer> mProfileServicesState = new HashMap<String,Integer>(); 101 private int mCurrentRequestId; 102 103 public void onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) { 104 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED); 105 m.obj = device; 106 m.arg1 = profileId; 107 m.arg2 = newState; 108 Bundle b = new Bundle(1); 109 b.putInt("prevState", prevState); 110 m.setData(b); 111 mHandler.sendMessage(m); 112 } 113 114 private void processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) { 115 if (mBluetoothService != null) { 116 try { 117 mBluetoothService.sendConnectionStateChange(device, profileId, newState, 118 prevState); 119 } catch (RemoteException re) { 120 Log.e(TAG, "",re); 121 } 122 } 123 } 124 125 public void onProfileServiceStateChanged(String serviceName, int state) { 126 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 127 m.obj=serviceName; 128 m.arg1 = state; 129 mHandler.sendMessage(m); 130 } 131 132 private void processProfileServiceStateChanged(String serviceName, int state) { 133 boolean doUpdate=false; 134 boolean isTurningOn; 135 boolean isTurningOff; 136 137 synchronized (mProfileServicesState) { 138 Integer prevState = mProfileServicesState.get(serviceName); 139 if (prevState != null && prevState != state) { 140 mProfileServicesState.put(serviceName,state); 141 doUpdate=true; 142 } 143 } 144 if (DBG) Log.d(TAG,"onProfileServiceStateChange: serviceName=" + serviceName + ", state = " + state +", doUpdate = " + doUpdate); 145 146 if (!doUpdate) { 147 return; 148 } 149 150 synchronized (mAdapterStateMachine) { 151 isTurningOff = mAdapterStateMachine.isTurningOff(); 152 isTurningOn = mAdapterStateMachine.isTurningOn(); 153 } 154 155 if (isTurningOff) { 156 //Process stop or disable pending 157 //Check if all services are stopped if so, do cleanup 158 //if (DBG) Log.d(TAG,"Checking if all profiles are stopped..."); 159 synchronized (mProfileServicesState) { 160 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator(); 161 while (i.hasNext()) { 162 Map.Entry<String,Integer> entry = i.next(); 163 if (BluetoothAdapter.STATE_OFF != entry.getValue()) { 164 Log.d(TAG, "Profile still running: " + entry.getKey()); 165 return; 166 } 167 } 168 } 169 if (DBG) Log.d(TAG, "All profile services stopped..."); 170 onProfilesStopped(); 171 } else if (isTurningOn) { 172 //Process start pending 173 //Check if all services are started if so, update state 174 //if (DBG) Log.d(TAG,"Checking if all profiles are running..."); 175 synchronized (mProfileServicesState) { 176 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator(); 177 while (i.hasNext()) { 178 Map.Entry<String,Integer> entry = i.next(); 179 if (BluetoothAdapter.STATE_ON != entry.getValue()) { 180 Log.d(TAG, "Profile still not running:" + entry.getKey()); 181 return; 182 } 183 } 184 } 185 if (DBG) Log.d(TAG, "All profile services started."); 186 onProfilesStarted(); 187 } 188 } 189 190 @Override 191 public void onCreate() { 192 super.onCreate(); 193 if (DBG) debugLog("onCreate"); 194 mContext = this; 195 sAdapterService = this; 196 mAdapterProperties = new AdapterProperties(this, mContext); 197 mAdapterStateMachine = new AdapterState(this, mContext, mAdapterProperties); 198 mJniCallbacks = JniCallbacks.getInstance(null, mAdapterProperties,mAdapterStateMachine,null); 199 initNative(); 200 mNativeAvailable=true; 201 mAdapterStateMachine.start(); 202 203 //Load the name and address 204 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR); 205 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME); 206 } 207 208 @Override 209 public IBinder onBind(Intent intent) { 210 if (DBG) debugLog("onBind"); 211 return mBinder; 212 } 213 public boolean onUnbind(Intent intent) { 214 if (DBG) debugLog("onUnbind"); 215 return super.onUnbind(intent); 216 } 217 218 public void onDestroy() { 219 debugLog("****onDestroy()********"); 220 mHandler.removeMessages(MESSAGE_SHUTDOWN); 221 cleanup(); 222 } 223 224 public int onStartCommand(Intent intent ,int flags, int startId) { 225 226 mCurrentRequestId = startId; 227 if (DBG) debugLog("onStartCommand: flags = " + flags + ", startId = " + startId); 228 if (checkCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM)!=PackageManager.PERMISSION_GRANTED) { 229 Log.e(TAG, "Permission denied!"); 230 return ADAPTER_SERVICE_TYPE; 231 } 232 233 //Check if we are restarting 234 if (intent == null) { 235 debugLog("Restarting AdapterService"); 236 return ADAPTER_SERVICE_TYPE; 237 } 238 239 //Get action and check if valid. If invalid, ignore and return 240 String action = intent.getStringExtra(EXTRA_ACTION); 241 debugLog("onStartCommand(): action = " + action); 242 if (!ACTION_SERVICE_STATE_CHANGED.equals(action)) { 243 Log.w(TAG,"Unknown action: " + action); 244 return ADAPTER_SERVICE_TYPE; 245 } 246 247 //Check state of request. If invalid, ignore and return 248 int state= intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.ERROR); 249 debugLog("onStartCommand(): state = " + Utils.debugGetAdapterStateString(state)); 250 251 //Cancel any pending shutdown requests 252 synchronized (mHandler) { 253 mHandler.removeMessages(MESSAGE_SHUTDOWN); 254 } 255 256 if (state == BluetoothAdapter.STATE_OFF) { 257 Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 258 m.arg1= startId; 259 mAdapterStateMachine.sendMessage(m); 260 } else if (state == BluetoothAdapter.STATE_ON) { 261 Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 262 m.arg1= startId; 263 mAdapterStateMachine.sendMessage(m); 264 } else { 265 Log.w(TAG,"Invalid state: " + action); 266 return ADAPTER_SERVICE_TYPE; 267 } 268 return ADAPTER_SERVICE_TYPE; 269 } 270 271 void processStart() { 272 if (DBG) debugLog("processStart()"); 273 274 //Initialize data objects 275 for (int i=0; i < SUPPORTED_PROFILE_SERVICES.length;i++) { 276 mProfileServicesState.put(SUPPORTED_PROFILE_SERVICES[i].getName(),BluetoothAdapter.STATE_OFF); 277 } 278 279 mRemoteDevices = new RemoteDevices(this, mContext); 280 mRemoteDevices.init(); 281 mAdapterProperties.init(mRemoteDevices); 282 mBondStateMachine = new BondStateMachine(this, mContext, mAdapterProperties, mRemoteDevices); 283 mJniCallbacks.init(mRemoteDevices, mAdapterProperties,mAdapterStateMachine,mBondStateMachine); 284 285 //Init BluetoothManager 286 if (DBG) {debugLog("processStart(): Initializing Bluetooth Manager");} 287 IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE); 288 if (b != null) { 289 mBluetoothManager = IBluetoothManager.Stub.asInterface(b); 290 if (mBluetoothManager != null) { 291 try { 292 Log.d(TAG, "FRED: Registering manager callback " + mManagerCallback); 293 mBluetoothService = mBluetoothManager.registerAdapter(mManagerCallback); 294 } catch (RemoteException re) { 295 Log.e(TAG, "",re); 296 } 297 } 298 } 299 300 //Start Bond State Machine 301 if (DBG) {debugLog("processStart(): Starting Bond State Machine");} 302 mBondStateMachine.start(); 303 304 //Start profile services 305 if (SUPPORTED_PROFILE_SERVICES.length==0 || mProfilesStarted) { 306 //Skip starting profiles and go to next step 307 if (DBG) {debugLog("processStart(): Profile Services started");} 308 Message m = mAdapterStateMachine.obtainMessage(AdapterState.STARTED); 309 mAdapterStateMachine.sendMessage(m); 310 } else { 311 //Startup all profile services 312 setProfileServiceState(SUPPORTED_PROFILE_SERVICES,BluetoothAdapter.STATE_ON); 313 } 314 } 315 316 void startBluetoothDisable() { 317 Log.d(TAG,"startBluetoothDisable()"); 318 Message m = mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE); 319 mAdapterStateMachine.sendMessage(m); 320 } 321 322 void onProfilesStarted(){ 323 Log.d(TAG,"onProfilesStarted()"); 324 mProfilesStarted=true; 325 Message m = mAdapterStateMachine.obtainMessage(AdapterState.STARTED); 326 mAdapterStateMachine.sendMessage(m); 327 } 328 329 void onProfilesStopped() { 330 Log.d(TAG,"onProfilesStopped()"); 331 mProfilesStarted=false; 332 //Message m = mAdapterStateMachine.obtainMessage(AdapterState.DISABLE); 333 Message m = mAdapterStateMachine.obtainMessage(AdapterState.STOPPED); 334 mAdapterStateMachine.sendMessage(m); 335 } 336 337 338 boolean stopProfileServices() { 339 if (SUPPORTED_PROFILE_SERVICES.length==0 || !mProfilesStarted) { 340 if (DBG) {debugLog("processDisable(): No profiles services to stop or already stopped.");} 341 return false; 342 } 343 setProfileServiceState(SUPPORTED_PROFILE_SERVICES,BluetoothAdapter.STATE_OFF); 344 return true; 345 } 346 347 void processStopped() { 348 Log.d(TAG, "processStopped()"); 349 350 if (mBluetoothManager != null) { 351 try { 352 Log.d(TAG,"FRED: Unregistering manager callback " + mManagerCallback); 353 mBluetoothManager.unregisterAdapter(mManagerCallback); 354 } catch (RemoteException re) { 355 Log.e(TAG, "",re); 356 } 357 } 358 mBondStateMachine.quit(); 359 mBondStateMachine.cleanup(); 360 mBondStateMachine = null; 361 } 362 363 void startShutdown(int requestId) { 364 debugLog("startShutdown(): requestId = " + requestId + ", currentRequestId=" + mCurrentRequestId); 365 if (requestId <0) { 366 Log.w(TAG, "Ignoring shutdown request. Invalid requestId"); 367 return; 368 } 369 370 Message m = mHandler.obtainMessage(MESSAGE_SHUTDOWN); 371 synchronized(mHandler) { 372 mHandler.sendMessageDelayed(m, SHUTDOWN_TIMEOUT); 373 } 374 stopSelfResult(requestId); 375 } 376 377 void cleanup () { 378 if (DBG)debugLog("cleanup()"); 379 380 if (mNativeAvailable) { 381 Log.d(TAG, "Cleaning up adapter native...."); 382 cleanupNative(); 383 Log.d(TAG, "Done cleaning up adapter native...."); 384 mNativeAvailable=false; 385 } 386 387 if (mAdapterStateMachine != null) { 388 mAdapterStateMachine.quit(); 389 mAdapterStateMachine.cleanup(); 390 mAdapterStateMachine = null; 391 } 392 393 if (mRemoteDevices != null) { 394 mRemoteDevices.cleanup(); 395 mRemoteDevices = null; 396 } 397 398 if (mAdapterProperties != null) { 399 mAdapterProperties.cleanup(); 400 mAdapterProperties = null; 401 } 402 403 mProfileServicesState.clear(); 404 if (DBG)debugLog("cleanup() done"); 405 } 406 407 final private IBluetoothManagerCallback mManagerCallback = 408 new IBluetoothManagerCallback.Stub() { 409 public void onBluetoothServiceUp(IBluetooth bluetoothService) { 410 if (DBG) Log.d(TAG, "onBluetoothServiceUp"); 411 synchronized (mManagerCallback) { 412 mBluetoothService = bluetoothService; 413 } 414 } 415 416 public void onBluetoothServiceDown() { 417 if (DBG) Log.d(TAG, "onBluetoothServiceDown " + this); 418 synchronized (mManagerCallback) { 419 mBluetoothService = null; 420 } 421 } 422 }; 423 424 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1; 425 private static final int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED=20; 426 private static final int MESSAGE_SHUTDOWN= 100; 427 private static final int SHUTDOWN_TIMEOUT=2000; 428 429 private final Handler mHandler = new Handler() { 430 @Override 431 public void handleMessage(Message msg) { 432 if (DBG) debugLog("Message: " + msg.what); 433 434 switch (msg.what) { 435 case MESSAGE_SHUTDOWN: { 436 if (DBG) Log.d(TAG,"***SHUTDOWN: TIMEOUT!!! Forcing shutdown..."); 437 stopSelf(); 438 } 439 break; 440 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: { 441 if(DBG) debugLog("MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 442 processProfileServiceStateChanged((String) msg.obj, msg.arg1); 443 } 444 break; 445 case MESSAGE_PROFILE_CONNECTION_STATE_CHANGED: { 446 if (DBG) debugLog( "MESSAGE_PROFILE_CONNECTION_STATE_CHANGED"); 447 processProfileStateChanged((BluetoothDevice) msg.obj, msg.arg1,msg.arg2, msg.getData().getInt("prevState",BluetoothAdapter.ERROR)); 448 } 449 break; 450 } 451 } 452 }; 453 454 @SuppressWarnings("rawtypes") 455 private void setProfileServiceState(Class[] services, int state) { 456 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 457 Log.w(TAG,"setProfileServiceState(): invalid state...Leaving..."); 458 return; 459 } 460 461 int expectedCurrentState= BluetoothAdapter.STATE_OFF; 462 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 463 if (state == BluetoothAdapter.STATE_OFF) { 464 expectedCurrentState= BluetoothAdapter.STATE_ON; 465 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 466 } 467 468 for (int i=0; i <services.length;i++) { 469 String serviceName = services[i].getName(); 470 Integer serviceState = mProfileServicesState.get(serviceName); 471 if(serviceState != null && serviceState != expectedCurrentState) { 472 Log.w(TAG, "Unable to " + (state == BluetoothAdapter.STATE_OFF? "start" : "stop" ) +" service " + 473 serviceName+". Invalid state: " + serviceState); 474 continue; 475 } 476 477 if (DBG) { 478 Log.w(TAG, (state == BluetoothAdapter.STATE_OFF? "Stopping" : "Starting" ) +" service " + 479 serviceName); 480 } 481 482 mProfileServicesState.put(serviceName,pendingState); 483 Intent intent = new Intent(this,services[i]); 484 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); 485 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); 486 startService(intent); 487 } 488 } 489 490 /** 491 * Handlers for incoming service calls 492 */ 493 private final IBluetooth.Stub mBinder = new IBluetooth.Stub() { 494 public boolean isEnabled() { 495 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 496 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 497 } 498 499 public int getState() { 500 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 501 debugLog("getState(): mAdapterProperties: " + mAdapterProperties); 502 return mAdapterProperties.getState(); 503 } 504 505 public boolean enable() { 506 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 507 "Need BLUETOOTH ADMIN permission"); 508 if (DBG) debugLog("enable() called..."); 509 Message m = 510 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 511 m.arg1 = 1; //persist state 512 mAdapterStateMachine.sendMessage(m); 513 return true; 514 } 515 516 public boolean disable(boolean persist) { 517 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 518 "Need BLUETOOTH ADMIN permission"); 519 if (DBG) debugLog("disable() called..."); 520 int val = (persist ? 1 : 0); 521 Message m = 522 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 523 m.arg1 = val; 524 mAdapterStateMachine.sendMessage(m); 525 return true; 526 } 527 528 public String getAddress() { 529 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 530 String addrString = null; 531 byte[] address = mAdapterProperties.getAddress(); 532 return Utils.getAddressStringFromByte(address); 533 } 534 535 public ParcelUuid[] getUuids() { 536 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 537 return mAdapterProperties.getUuids(); 538 } 539 540 public String getName() { 541 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 542 "Need BLUETOOTH permission"); 543 try { 544 return mAdapterProperties.getName(); 545 } catch (Throwable t) { 546 Log.d(TAG, "Unexpected exception while calling getName()",t); 547 } 548 return null; 549 } 550 551 public boolean setName(String name) { 552 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 553 "Need BLUETOOTH ADMIN permission"); 554 return mAdapterProperties.setName(name); 555 } 556 557 public int getScanMode() { 558 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 559 return mAdapterProperties.getScanMode(); 560 } 561 562 public boolean setScanMode(int mode, int duration) { 563 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 564 setDiscoverableTimeout(duration); 565 566 int newMode = convertScanModeToHal(mode); 567 return mAdapterProperties.setScanMode(newMode); 568 } 569 570 public int getDiscoverableTimeout() { 571 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 572 return mAdapterProperties.getDiscoverableTimeout(); 573 } 574 575 public boolean setDiscoverableTimeout(int timeout) { 576 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 577 return mAdapterProperties.setDiscoverableTimeout(timeout); 578 } 579 580 public boolean startDiscovery() { 581 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 582 "Need BLUETOOTH ADMIN permission"); 583 return startDiscoveryNative(); 584 } 585 586 public boolean cancelDiscovery() { 587 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 588 "Need BLUETOOTH ADMIN permission"); 589 return cancelDiscoveryNative(); 590 } 591 592 public boolean isDiscovering() { 593 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 594 return mAdapterProperties.isDiscovering(); 595 } 596 597 public BluetoothDevice[] getBondedDevices() { 598 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 599 debugLog("Get Bonded Devices being called"); 600 return mAdapterProperties.getBondedDevices(); 601 } 602 603 public int getAdapterConnectionState() { 604 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 605 return mAdapterProperties.getConnectionState(); 606 } 607 608 public int getProfileConnectionState(int profile) { 609 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 610 return mAdapterProperties.getProfileConnectionState(profile); 611 } 612 613 public boolean createBond(BluetoothDevice device) { 614 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 615 "Need BLUETOOTH ADMIN permission"); 616 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 617 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 618 return false; 619 } 620 621 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 622 msg.obj = device; 623 mBondStateMachine.sendMessage(msg); 624 return true; 625 } 626 627 public boolean cancelBondProcess(BluetoothDevice device) { 628 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 629 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 630 return cancelBondNative(addr); 631 } 632 633 public boolean removeBond(BluetoothDevice device) { 634 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 635 "Need BLUETOOTH ADMIN permission"); 636 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 637 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 638 return false; 639 } 640 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 641 msg.obj = device; 642 mBondStateMachine.sendMessage(msg); 643 return true; 644 } 645 646 public int getBondState(BluetoothDevice device) { 647 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 648 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 649 if (deviceProp == null) { 650 return BluetoothDevice.BOND_NONE; 651 } 652 return deviceProp.getBondState(); 653 } 654 655 public String getRemoteName(BluetoothDevice device) { 656 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 657 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 658 if (deviceProp == null) return null; 659 return deviceProp.getName(); 660 } 661 662 public String getRemoteAlias(BluetoothDevice device) { 663 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 664 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 665 if (deviceProp == null) return null; 666 return deviceProp.getAlias(); 667 } 668 669 public boolean setRemoteAlias(BluetoothDevice device, String name) { 670 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 671 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 672 if (deviceProp == null) return false; 673 deviceProp.setAlias(name); 674 return true; 675 } 676 677 public int getRemoteClass(BluetoothDevice device) { 678 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 679 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 680 if (deviceProp == null) return 0; 681 682 return deviceProp.getBluetoothClass(); 683 } 684 685 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 686 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 687 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 688 if (deviceProp == null) return null; 689 return deviceProp.getUuids(); 690 } 691 692 public boolean fetchRemoteUuids(BluetoothDevice device) { 693 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 694 mRemoteDevices.fetchUuids(device); 695 return true; 696 } 697 698 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 699 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 700 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 701 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 702 return false; 703 } 704 705 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 706 return pinReplyNative(addr, accept, len, pinCode); 707 } 708 709 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 710 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 711 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 712 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 713 return false; 714 } 715 716 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 717 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept, 718 Utils.byteArrayToInt(passkey)); 719 } 720 721 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 722 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 723 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 724 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 725 return false; 726 } 727 728 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 729 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 730 accept, 0); 731 } 732 733 public void sendConnectionStateChange(BluetoothDevice 734 device, int profile, int state, int prevState) { 735 // TODO(BT) permission check? 736 // Since this is a binder call check if Bluetooth is on still 737 if (getState() == BluetoothAdapter.STATE_OFF) return; 738 739 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 740 741 } 742 743 public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 744 ParcelUuid uuid, int port, int flag) { 745 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 746 int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()), 747 type, Utils.uuidToByteArray(uuid), port, flag); 748 if (fd < 0) { 749 errorLog("Failed to connect socket"); 750 return null; 751 } 752 return ParcelFileDescriptor.adoptFd(fd); 753 } 754 755 public ParcelFileDescriptor createSocketChannel(int type, String serviceName, 756 ParcelUuid uuid, int port, int flag) { 757 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 758 int fd = createSocketChannelNative(type, serviceName, 759 Utils.uuidToByteArray(uuid), port, flag); 760 if (fd < 0) { 761 errorLog("Failed to create socket channel"); 762 return null; 763 } 764 return ParcelFileDescriptor.adoptFd(fd); 765 } 766 }; 767 768 private int convertScanModeToHal(int mode) { 769 switch (mode) { 770 case BluetoothAdapter.SCAN_MODE_NONE: 771 return AbstractionLayer.BT_SCAN_MODE_NONE; 772 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 773 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 774 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 775 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 776 } 777 errorLog("Incorrect scan mode in convertScanModeToHal"); 778 return -1; 779 } 780 781 int convertScanModeFromHal(int mode) { 782 switch (mode) { 783 case AbstractionLayer.BT_SCAN_MODE_NONE: 784 return BluetoothAdapter.SCAN_MODE_NONE; 785 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 786 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 787 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 788 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 789 } 790 errorLog("Incorrect scan mode in convertScanModeFromHal"); 791 return -1; 792 } 793 794 private void debugLog(String msg) { 795 Log.d(TAG +"(" +hashCode()+")", msg); 796 } 797 798 private void errorLog(String msg) { 799 Log.e(TAG +"(" +hashCode()+")", msg); 800 } 801 802 private native static void classInitNative(); 803 private native boolean initNative(); 804 private native void cleanupNative(); 805 /*package*/ native boolean enableNative(); 806 /*package*/ native boolean disableNative(); 807 /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val); 808 /*package*/ native boolean getAdapterPropertiesNative(); 809 /*package*/ native boolean getAdapterPropertyNative(int type); 810 /*package*/ native boolean setAdapterPropertyNative(int type); 811 /*package*/ native boolean 812 setDevicePropertyNative(byte[] address, int type, byte[] val); 813 /*package*/ native boolean getDevicePropertyNative(byte[] address, int type); 814 815 /*package*/ native boolean createBondNative(byte[] address); 816 /*package*/ native boolean removeBondNative(byte[] address); 817 /*package*/ native boolean cancelBondNative(byte[] address); 818 819 private native boolean startDiscoveryNative(); 820 private native boolean cancelDiscoveryNative(); 821 822 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 823 private native boolean sspReplyNative(byte[] address, int type, boolean 824 accept, int passkey); 825 826 /*package*/ native boolean getRemoteServicesNative(byte[] address); 827 828 // TODO(BT) move this to ../btsock dir 829 private native int connectSocketNative(byte[] address, int type, 830 byte[] uuid, int port, int flag); 831 private native int createSocketChannelNative(int type, String serviceName, 832 byte[] uuid, int port, int flag); 833} 834