AdapterService.java revision 15d36984a79d6e35c659edb0efdf929f0b526bd5
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.IBluetoothCallback; 18import android.bluetooth.IBluetoothManager; 19import android.bluetooth.IBluetoothManagerCallback; 20import android.content.BroadcastReceiver; 21import android.content.ContentResolver; 22import android.content.Context; 23import android.content.Intent; 24import android.content.IntentFilter; 25import android.os.Binder; 26import android.os.Bundle; 27import android.os.Handler; 28import android.os.IBinder; 29import android.os.Message; 30import android.os.ParcelFileDescriptor; 31import android.os.ParcelUuid; 32import android.os.RemoteCallbackList; 33import android.os.RemoteException; 34import android.provider.Settings; 35import android.util.Log; 36import android.util.Pair; 37import com.android.bluetooth.a2dp.A2dpService; 38import com.android.bluetooth.hid.HidService; 39import com.android.bluetooth.hfp.HeadsetService; 40import com.android.bluetooth.hdp.HealthService; 41import com.android.bluetooth.pan.PanService; 42import com.android.bluetooth.R; 43import com.android.bluetooth.Utils; 44import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 45import java.io.FileDescriptor; 46import java.io.IOException; 47import java.util.ArrayList; 48import java.util.HashMap; 49import java.util.Set; 50import java.util.Map; 51import java.util.Iterator; 52import java.util.Map.Entry; 53import android.content.pm.PackageManager; 54import android.os.ServiceManager; 55 56public class AdapterService extends Service { 57 private static final String TAG = "BluetoothAdapterService"; 58 private static final boolean DBG = true; 59 private static final boolean TRACE_REF = true; 60 //For Debugging only 61 private static int sRefCount=0; 62 63 public static final String ACTION_LOAD_ADAPTER_PROPERTIES="com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES"; 64 public static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED"; 65 public static final String EXTRA_ACTION="action"; 66 67 static final String BLUETOOTH_ADMIN_PERM = 68 android.Manifest.permission.BLUETOOTH_ADMIN; 69 static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 70 71 private static final int ADAPTER_SERVICE_TYPE=Service.START_STICKY; 72 73 static { 74 classInitNative(); 75 } 76 77 private static AdapterService sAdapterService; 78 public static synchronized AdapterService getAdapterService(){ 79 if (sAdapterService != null && !sAdapterService.mCleaningUp) { 80 if (DBG) Log.d(TAG, "getAdapterService(): returning " + sAdapterService); 81 return sAdapterService; 82 } 83 if (DBG) { 84 if (sAdapterService == null) { 85 Log.d(TAG, "getAdapterService(): service not available"); 86 } else if (sAdapterService.mCleaningUp) { 87 Log.d(TAG,"getAdapterService(): service is cleaning up"); 88 } 89 } 90 return null; 91 } 92 93 private static synchronized void setAdapterService(AdapterService instance) { 94 if (instance != null && !instance.mCleaningUp) { 95 if (DBG) Log.d(TAG, "setAdapterService(): set to: " + sAdapterService); 96 sAdapterService = instance; 97 } else { 98 if (DBG) { 99 if (sAdapterService == null) { 100 Log.d(TAG, "setAdapterService(): service not available"); 101 } else if (sAdapterService.mCleaningUp) { 102 Log.d(TAG,"setAdapterService(): service is cleaning up"); 103 } 104 } 105 } 106 } 107 108 private static synchronized void clearAdapterService() { 109 sAdapterService = null; 110 } 111 112 private AdapterProperties mAdapterProperties; 113 private AdapterState mAdapterStateMachine; 114 private BondStateMachine mBondStateMachine; 115 private JniCallbacks mJniCallbacks; 116 private RemoteDevices mRemoteDevices; 117 private boolean mProfilesStarted; 118 private boolean mNativeAvailable; 119 private boolean mCleaningUp; 120 private HashMap<String,Integer> mProfileServicesState = new HashMap<String,Integer>(); 121 private RemoteCallbackList<IBluetoothCallback> mCallbacks;//Only BluetoothManagerService should be registered 122 private int mCurrentRequestId; 123 124 public AdapterService() { 125 super(); 126 if (TRACE_REF) { 127 synchronized (AdapterService.class) { 128 sRefCount++; 129 Log.d(TAG, "REFCOUNT: CREATED. INSTANCE_COUNT" + sRefCount); 130 } 131 } 132 } 133 134 public void onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) { 135 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED); 136 m.obj = device; 137 m.arg1 = profileId; 138 m.arg2 = newState; 139 Bundle b = new Bundle(1); 140 b.putInt("prevState", prevState); 141 m.setData(b); 142 mHandler.sendMessage(m); 143 } 144 145 private void processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) { 146 IBluetooth.Stub binder = mBinder; 147 if (binder != null) { 148 try { 149 binder.sendConnectionStateChange(device, profileId, newState,prevState); 150 } catch (RemoteException re) { 151 Log.e(TAG, "",re); 152 } 153 } 154 } 155 156 public void onProfileServiceStateChanged(String serviceName, int state) { 157 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 158 m.obj=serviceName; 159 m.arg1 = state; 160 mHandler.sendMessage(m); 161 } 162 163 private void processProfileServiceStateChanged(String serviceName, int state) { 164 boolean doUpdate=false; 165 boolean isTurningOn; 166 boolean isTurningOff; 167 168 synchronized (mProfileServicesState) { 169 Integer prevState = mProfileServicesState.get(serviceName); 170 if (prevState != null && prevState != state) { 171 mProfileServicesState.put(serviceName,state); 172 doUpdate=true; 173 } 174 } 175 if (DBG) Log.d(TAG,"onProfileServiceStateChange: serviceName=" + serviceName + ", state = " + state +", doUpdate = " + doUpdate); 176 177 if (!doUpdate) { 178 return; 179 } 180 181 synchronized (mAdapterStateMachine) { 182 isTurningOff = mAdapterStateMachine.isTurningOff(); 183 isTurningOn = mAdapterStateMachine.isTurningOn(); 184 } 185 186 if (isTurningOff) { 187 //Process stop or disable pending 188 //Check if all services are stopped if so, do cleanup 189 //if (DBG) Log.d(TAG,"Checking if all profiles are stopped..."); 190 synchronized (mProfileServicesState) { 191 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator(); 192 while (i.hasNext()) { 193 Map.Entry<String,Integer> entry = i.next(); 194 if (BluetoothAdapter.STATE_OFF != entry.getValue()) { 195 Log.d(TAG, "Profile still running: " + entry.getKey()); 196 return; 197 } 198 } 199 } 200 if (DBG) Log.d(TAG, "All profile services stopped..."); 201 //Send message to state machine 202 mProfilesStarted=false; 203 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STOPPED)); 204 } else if (isTurningOn) { 205 //Process start pending 206 //Check if all services are started if so, update state 207 //if (DBG) Log.d(TAG,"Checking if all profiles are running..."); 208 synchronized (mProfileServicesState) { 209 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator(); 210 while (i.hasNext()) { 211 Map.Entry<String,Integer> entry = i.next(); 212 if (BluetoothAdapter.STATE_ON != entry.getValue()) { 213 Log.d(TAG, "Profile still not running:" + entry.getKey()); 214 return; 215 } 216 } 217 } 218 if (DBG) Log.d(TAG, "All profile services started."); 219 mProfilesStarted=true; 220 //Send message to state machine 221 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED)); 222 } 223 } 224 225 @Override 226 public void onCreate() { 227 super.onCreate(); 228 if (DBG) debugLog("onCreate"); 229 mBinder = new AdapterServiceBinder(this); 230 mAdapterProperties = new AdapterProperties(this); 231 mAdapterStateMachine = new AdapterState(this, mAdapterProperties); 232 mJniCallbacks = new JniCallbacks(mAdapterStateMachine, mAdapterProperties); 233 initNative(); 234 mNativeAvailable=true; 235 mAdapterStateMachine.start(); 236 mCallbacks = new RemoteCallbackList<IBluetoothCallback>(); 237 //Load the name and address 238 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR); 239 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME); 240 241 } 242 243 @Override 244 public IBinder onBind(Intent intent) { 245 if (DBG) debugLog("onBind"); 246 return mBinder; 247 } 248 public boolean onUnbind(Intent intent) { 249 if (DBG) debugLog("onUnbind"); 250 return super.onUnbind(intent); 251 } 252 253 public void onDestroy() { 254 debugLog("****onDestroy()********"); 255 mHandler.removeMessages(MESSAGE_SHUTDOWN); 256 cleanup(); 257 } 258 259 void processStart() { 260 if (DBG) debugLog("processStart()"); 261 Class[] supportedProfileServices = Config.getSupportedProfiles(); 262 //Initialize data objects 263 for (int i=0; i < supportedProfileServices.length;i++) { 264 mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF); 265 } 266 mRemoteDevices = new RemoteDevices(this); 267 mBondStateMachine = new BondStateMachine(this, mAdapterProperties, mRemoteDevices); 268 mAdapterProperties.init(mRemoteDevices); 269 mJniCallbacks.init(mBondStateMachine,mRemoteDevices); 270 271 //Start Bond State Machine 272 if (DBG) {debugLog("processStart(): Starting Bond State Machine");} 273 mBondStateMachine.start(); 274 275 //FIXME: Set static instance here??? 276 setAdapterService(this); 277 278 //Start profile services 279 if (!mProfilesStarted && supportedProfileServices.length >0) { 280 //Startup all profile services 281 setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON); 282 }else { 283 if (DBG) {debugLog("processStart(): Profile Services alreay started");} 284 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED)); 285 } 286 } 287 288 void startBluetoothDisable() { 289 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE)); 290 } 291 292 boolean stopProfileServices() { 293 Class[] supportedProfileServices = Config.getSupportedProfiles(); 294 if (mProfilesStarted && supportedProfileServices.length>0) { 295 setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF); 296 return true; 297 } else { 298 if (DBG) {debugLog("stopProfileServices(): No profiles services to stop or already stopped.");} 299 return false; 300 } 301 } 302 303 void updateAdapterState(int prevState, int newState){ 304 if (mCallbacks !=null) { 305 int n=mCallbacks.beginBroadcast(); 306 Log.d(TAG,"Broadcasting updateAdapterState() to " + n + " receivers."); 307 for (int i=0; i <n;i++) { 308 try { 309 mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState); 310 } catch (RemoteException e) { 311 Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e); 312 } 313 } 314 mCallbacks.finishBroadcast(); 315 } 316 } 317 318 void cleanup () { 319 if (DBG)debugLog("cleanup()"); 320 if (mCleaningUp) { 321 Log.w(TAG,"*************service already starting to cleanup... Ignoring cleanup request........."); 322 return; 323 } 324 325 mCleaningUp = true; 326 327 if (mAdapterStateMachine != null) { 328 mAdapterStateMachine.doQuit(); 329 mAdapterStateMachine.cleanup(); 330 } 331 332 if (mBondStateMachine != null) { 333 mBondStateMachine.doQuit(); 334 mBondStateMachine.cleanup(); 335 } 336 337 if (mRemoteDevices != null) { 338 mRemoteDevices.cleanup(); 339 } 340 341 if (mNativeAvailable) { 342 Log.d(TAG, "Cleaning up adapter native...."); 343 cleanupNative(); 344 Log.d(TAG, "Done cleaning up adapter native...."); 345 mNativeAvailable=false; 346 } 347 348 if (mAdapterProperties != null) { 349 mAdapterProperties.cleanup(); 350 } 351 352 if (mJniCallbacks != null) { 353 mJniCallbacks.cleanup(); 354 } 355 356 if (mProfileServicesState != null) { 357 mProfileServicesState.clear(); 358 } 359 360 clearAdapterService(); 361 362 if (mBinder != null) { 363 mBinder.cleanup(); 364 mBinder = null; //Do not remove. Otherwise Binder leak! 365 } 366 367 if (mCallbacks !=null) { 368 mCallbacks.kill(); 369 } 370 371 if (DBG)debugLog("cleanup() done"); 372 } 373 374 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1; 375 private static final int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED=20; 376 private static final int MESSAGE_SHUTDOWN= 100; 377 private static final int SHUTDOWN_TIMEOUT=2000; 378 379 private final Handler mHandler = new Handler() { 380 @Override 381 public void handleMessage(Message msg) { 382 if (DBG) debugLog("Message: " + msg.what); 383 384 switch (msg.what) { 385 case MESSAGE_SHUTDOWN: { 386 if (DBG) Log.d(TAG,"***SHUTDOWN: TIMEOUT!!! Forcing shutdown..."); 387 stopSelf(); 388 } 389 break; 390 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: { 391 if(DBG) debugLog("MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 392 processProfileServiceStateChanged((String) msg.obj, msg.arg1); 393 } 394 break; 395 case MESSAGE_PROFILE_CONNECTION_STATE_CHANGED: { 396 if (DBG) debugLog( "MESSAGE_PROFILE_CONNECTION_STATE_CHANGED"); 397 processProfileStateChanged((BluetoothDevice) msg.obj, msg.arg1,msg.arg2, msg.getData().getInt("prevState",BluetoothAdapter.ERROR)); 398 } 399 break; 400 } 401 } 402 }; 403 404 @SuppressWarnings("rawtypes") 405 private void setProfileServiceState(Class[] services, int state) { 406 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 407 Log.w(TAG,"setProfileServiceState(): invalid state...Leaving..."); 408 return; 409 } 410 411 int expectedCurrentState= BluetoothAdapter.STATE_OFF; 412 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 413 if (state == BluetoothAdapter.STATE_OFF) { 414 expectedCurrentState= BluetoothAdapter.STATE_ON; 415 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 416 } 417 418 for (int i=0; i <services.length;i++) { 419 String serviceName = services[i].getName(); 420 Integer serviceState = mProfileServicesState.get(serviceName); 421 if(serviceState != null && serviceState != expectedCurrentState) { 422 Log.w(TAG, "Unable to " + (state == BluetoothAdapter.STATE_OFF? "start" : "stop" ) +" service " + 423 serviceName+". Invalid state: " + serviceState); 424 continue; 425 } 426 427 if (DBG) { 428 Log.w(TAG, (state == BluetoothAdapter.STATE_OFF? "Stopping" : "Starting" ) +" service " + 429 serviceName); 430 } 431 432 mProfileServicesState.put(serviceName,pendingState); 433 Intent intent = new Intent(this,services[i]); 434 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); 435 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); 436 startService(intent); 437 } 438 } 439 440 private boolean isAvailable() { 441 return !mCleaningUp; 442 } 443 444 /** 445 * Handlers for incoming service calls 446 */ 447 private AdapterServiceBinder mBinder; 448 449 /** 450 * The Binder implementation must be declared to be a static class, with 451 * the AdapterService instance passed in the constructor. Furthermore, 452 * when the AdapterService shuts down, the reference to the AdapterService 453 * must be explicitly removed. 454 * 455 * Otherwise, a memory leak can occur from repeated starting/stopping the 456 * service...Please refer to android.os.Binder for further details on 457 * why an inner instance class should be avoided. 458 * 459 */ 460 private static class AdapterServiceBinder extends IBluetooth.Stub { 461 private AdapterService mService; 462 463 public AdapterServiceBinder(AdapterService svc) { 464 mService = svc; 465 } 466 public boolean cleanup() { 467 mService = null; 468 return true; 469 } 470 471 public AdapterService getService() { 472 if (mService != null && mService.isAvailable()) { 473 return mService; 474 } 475 return null; 476 } 477 public boolean isEnabled() { 478 AdapterService service = getService(); 479 if (service == null) return false; 480 return service.isEnabled(); 481 } 482 483 public int getState() { 484 AdapterService service = getService(); 485 if (service == null) return BluetoothAdapter.STATE_OFF; 486 return service.getState(); 487 } 488 489 public boolean enable() { 490 AdapterService service = getService(); 491 if (service == null) return false; 492 return service.enable(); 493 } 494 495 public boolean enableNoAutoConnect() { 496 // TODO(BT) 497 return false; 498 } 499 500 public boolean disable() { 501 AdapterService service = getService(); 502 if (service == null) return false; 503 return service.disable(); 504 } 505 506 public String getAddress() { 507 AdapterService service = getService(); 508 if (service == null) return null; 509 return service.getAddress(); 510 } 511 512 public ParcelUuid[] getUuids() { 513 AdapterService service = getService(); 514 if (service == null) return new ParcelUuid[0]; 515 return service.getUuids(); 516 } 517 518 public String getName() { 519 AdapterService service = getService(); 520 if (service == null) return null; 521 return service.getName(); 522 } 523 524 public boolean setName(String name) { 525 AdapterService service = getService(); 526 if (service == null) return false; 527 return service.setName(name); 528 } 529 530 public int getScanMode() { 531 AdapterService service = getService(); 532 if (service == null) return BluetoothAdapter.SCAN_MODE_NONE; 533 return service.getScanMode(); 534 } 535 536 public boolean setScanMode(int mode, int duration) { 537 AdapterService service = getService(); 538 if (service == null) return false; 539 return service.setScanMode(mode,duration); 540 } 541 542 public int getDiscoverableTimeout() { 543 AdapterService service = getService(); 544 if (service == null) return 0; 545 return service.getDiscoverableTimeout(); 546 } 547 548 public boolean setDiscoverableTimeout(int timeout) { 549 AdapterService service = getService(); 550 if (service == null) return false; 551 return service.setDiscoverableTimeout(timeout); 552 } 553 554 public boolean startDiscovery() { 555 AdapterService service = getService(); 556 if (service == null) return false; 557 return service.startDiscovery(); 558 } 559 560 public boolean cancelDiscovery() { 561 AdapterService service = getService(); 562 if (service == null) return false; 563 return service.cancelDiscovery(); 564 } 565 public boolean isDiscovering() { 566 AdapterService service = getService(); 567 if (service == null) return false; 568 return service.isDiscovering(); 569 } 570 571 public BluetoothDevice[] getBondedDevices() { 572 AdapterService service = getService(); 573 if (service == null) return new BluetoothDevice[0]; 574 return service.getBondedDevices(); 575 } 576 577 public int getAdapterConnectionState() { 578 AdapterService service = getService(); 579 if (service == null) return BluetoothAdapter.STATE_DISCONNECTED; 580 return service.getAdapterConnectionState(); 581 } 582 583 public int getProfileConnectionState(int profile) { 584 AdapterService service = getService(); 585 if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 586 return service.getProfileConnectionState(profile); 587 } 588 589 public boolean createBond(BluetoothDevice device) { 590 AdapterService service = getService(); 591 if (service == null) return false; 592 return service.createBond(device); 593 } 594 595 public boolean cancelBondProcess(BluetoothDevice device) { 596 AdapterService service = getService(); 597 if (service == null) return false; 598 return service.cancelBondProcess(device); 599 } 600 601 public boolean removeBond(BluetoothDevice device) { 602 AdapterService service = getService(); 603 if (service == null) return false; 604 return service.removeBond(device); 605 } 606 607 public int getBondState(BluetoothDevice device) { 608 AdapterService service = getService(); 609 if (service == null) return BluetoothDevice.BOND_NONE; 610 return service.getBondState(device); 611 } 612 613 public String getRemoteName(BluetoothDevice device) { 614 AdapterService service = getService(); 615 if (service == null) return null; 616 return service.getRemoteName(device); 617 } 618 619 public String getRemoteAlias(BluetoothDevice device) { 620 AdapterService service = getService(); 621 if (service == null) return null; 622 return service.getRemoteAlias(device); 623 } 624 625 public boolean setRemoteAlias(BluetoothDevice device, String name) { 626 AdapterService service = getService(); 627 if (service == null) return false; 628 return service.setRemoteAlias(device, name); 629 } 630 631 public int getRemoteClass(BluetoothDevice device) { 632 AdapterService service = getService(); 633 if (service == null) return 0; 634 return service.getRemoteClass(device); 635 } 636 637 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 638 AdapterService service = getService(); 639 if (service == null) return null; 640 return service.getRemoteUuids(device); 641 } 642 643 public boolean fetchRemoteUuids(BluetoothDevice device) { 644 AdapterService service = getService(); 645 if (service == null) return false; 646 return service.fetchRemoteUuids(device); 647 } 648 649 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 650 AdapterService service = getService(); 651 if (service == null) return false; 652 return service.setPin(device, accept, len, pinCode); 653 } 654 655 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 656 AdapterService service = getService(); 657 if (service == null) return false; 658 return service.setPasskey(device, accept, len, passkey); 659 } 660 661 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 662 AdapterService service = getService(); 663 if (service == null) return false; 664 return service.setPairingConfirmation(device, accept); 665 } 666 667 public void sendConnectionStateChange(BluetoothDevice 668 device, int profile, int state, int prevState) { 669 AdapterService service = getService(); 670 if (service == null) return; 671 service.sendConnectionStateChange(device, profile, state, prevState); 672 } 673 674 public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 675 ParcelUuid uuid, int port, int flag) { 676 AdapterService service = getService(); 677 if (service == null) return null; 678 return service.connectSocket(device, type, uuid, port, flag); 679 } 680 681 public ParcelFileDescriptor createSocketChannel(int type, String serviceName, 682 ParcelUuid uuid, int port, int flag) { 683 AdapterService service = getService(); 684 if (service == null) return null; 685 return service.createSocketChannel(type, serviceName, uuid, port, flag); 686 } 687 688 public void registerCallback(IBluetoothCallback cb) { 689 AdapterService service = getService(); 690 if (service == null) return ; 691 service.registerCallback(cb); 692 } 693 694 public void unregisterCallback(IBluetoothCallback cb) { 695 AdapterService service = getService(); 696 if (service == null) return ; 697 service.unregisterCallback(cb); 698 } 699 }; 700 701 702 //----API Methods-------- 703 boolean isEnabled() { 704 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 705 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 706 } 707 708 int getState() { 709 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 710 debugLog("getState(): mAdapterProperties: " + mAdapterProperties); 711 return mAdapterProperties.getState(); 712 } 713 714 boolean enable() { 715 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 716 "Need BLUETOOTH ADMIN permission"); 717 if (DBG) debugLog("enable() called..."); 718 Message m = 719 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 720 mAdapterStateMachine.sendMessage(m); 721 return true; 722 } 723 724 boolean disable() { 725 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 726 "Need BLUETOOTH ADMIN permission"); 727 if (DBG) debugLog("disable() called..."); 728 Message m = 729 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 730 mAdapterStateMachine.sendMessage(m); 731 return true; 732 } 733 734 String getAddress() { 735 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 736 String addrString = null; 737 byte[] address = mAdapterProperties.getAddress(); 738 return Utils.getAddressStringFromByte(address); 739 } 740 741 ParcelUuid[] getUuids() { 742 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 743 return mAdapterProperties.getUuids(); 744 } 745 746 String getName() { 747 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 748 "Need BLUETOOTH permission"); 749 try { 750 return mAdapterProperties.getName(); 751 } catch (Throwable t) { 752 Log.d(TAG, "Unexpected exception while calling getName()",t); 753 } 754 return null; 755 } 756 757 boolean setName(String name) { 758 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 759 "Need BLUETOOTH ADMIN permission"); 760 return mAdapterProperties.setName(name); 761 } 762 763 int getScanMode() { 764 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 765 return mAdapterProperties.getScanMode(); 766 } 767 768 boolean setScanMode(int mode, int duration) { 769 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 770 setDiscoverableTimeout(duration); 771 772 int newMode = convertScanModeToHal(mode); 773 return mAdapterProperties.setScanMode(newMode); 774 } 775 776 int getDiscoverableTimeout() { 777 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 778 return mAdapterProperties.getDiscoverableTimeout(); 779 } 780 781 boolean setDiscoverableTimeout(int timeout) { 782 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 783 return mAdapterProperties.setDiscoverableTimeout(timeout); 784 } 785 786 boolean startDiscovery() { 787 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 788 "Need BLUETOOTH ADMIN permission"); 789 return startDiscoveryNative(); 790 } 791 792 boolean cancelDiscovery() { 793 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 794 "Need BLUETOOTH ADMIN permission"); 795 return cancelDiscoveryNative(); 796 } 797 798 boolean isDiscovering() { 799 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 800 return mAdapterProperties.isDiscovering(); 801 } 802 803 BluetoothDevice[] getBondedDevices() { 804 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 805 debugLog("Get Bonded Devices being called"); 806 return mAdapterProperties.getBondedDevices(); 807 } 808 809 int getAdapterConnectionState() { 810 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 811 return mAdapterProperties.getConnectionState(); 812 } 813 814 int getProfileConnectionState(int profile) { 815 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 816 return mAdapterProperties.getProfileConnectionState(profile); 817 } 818 819 boolean createBond(BluetoothDevice device) { 820 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 821 "Need BLUETOOTH ADMIN permission"); 822 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 823 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 824 return false; 825 } 826 827 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 828 msg.obj = device; 829 mBondStateMachine.sendMessage(msg); 830 return true; 831 } 832 833 boolean cancelBondProcess(BluetoothDevice device) { 834 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 835 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 836 return cancelBondNative(addr); 837 } 838 839 boolean removeBond(BluetoothDevice device) { 840 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 841 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 842 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 843 return false; 844 } 845 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 846 msg.obj = device; 847 mBondStateMachine.sendMessage(msg); 848 return true; 849 } 850 851 int getBondState(BluetoothDevice device) { 852 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 853 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 854 if (deviceProp == null) { 855 return BluetoothDevice.BOND_NONE; 856 } 857 return deviceProp.getBondState(); 858 } 859 860 String getRemoteName(BluetoothDevice device) { 861 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 862 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 863 if (deviceProp == null) return null; 864 return deviceProp.getName(); 865 } 866 867 String getRemoteAlias(BluetoothDevice device) { 868 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 869 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 870 if (deviceProp == null) return null; 871 return deviceProp.getAlias(); 872 } 873 874 boolean setRemoteAlias(BluetoothDevice device, String name) { 875 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 876 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 877 if (deviceProp == null) return false; 878 deviceProp.setAlias(name); 879 return true; 880 } 881 882 int getRemoteClass(BluetoothDevice device) { 883 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 884 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 885 if (deviceProp == null) return 0; 886 887 return deviceProp.getBluetoothClass(); 888 } 889 890 ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 891 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 892 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 893 if (deviceProp == null) return null; 894 return deviceProp.getUuids(); 895 } 896 897 boolean fetchRemoteUuids(BluetoothDevice device) { 898 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 899 mRemoteDevices.fetchUuids(device); 900 return true; 901 } 902 903 boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 904 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 905 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 906 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 907 return false; 908 } 909 910 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 911 return pinReplyNative(addr, accept, len, pinCode); 912 } 913 914 boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 915 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 916 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 917 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 918 return false; 919 } 920 921 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 922 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept, 923 Utils.byteArrayToInt(passkey)); 924 } 925 926 boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 927 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 928 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 929 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 930 return false; 931 } 932 933 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 934 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 935 accept, 0); 936 } 937 938 void sendConnectionStateChange(BluetoothDevice 939 device, int profile, int state, int prevState) { 940 // TODO(BT) permission check? 941 // Since this is a binder call check if Bluetooth is on still 942 if (getState() == BluetoothAdapter.STATE_OFF) return; 943 944 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 945 946 } 947 948 ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 949 ParcelUuid uuid, int port, int flag) { 950 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 951 int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()), 952 type, Utils.uuidToByteArray(uuid), port, flag); 953 if (fd < 0) { 954 errorLog("Failed to connect socket"); 955 return null; 956 } 957 return ParcelFileDescriptor.adoptFd(fd); 958 } 959 960 ParcelFileDescriptor createSocketChannel(int type, String serviceName, 961 ParcelUuid uuid, int port, int flag) { 962 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 963 int fd = createSocketChannelNative(type, serviceName, 964 Utils.uuidToByteArray(uuid), port, flag); 965 if (fd < 0) { 966 errorLog("Failed to create socket channel"); 967 return null; 968 } 969 return ParcelFileDescriptor.adoptFd(fd); 970 } 971 972 void registerCallback(IBluetoothCallback cb) { 973 mCallbacks.register(cb); 974 } 975 976 void unregisterCallback(IBluetoothCallback cb) { 977 mCallbacks.unregister(cb); 978 } 979 980 private static int convertScanModeToHal(int mode) { 981 switch (mode) { 982 case BluetoothAdapter.SCAN_MODE_NONE: 983 return AbstractionLayer.BT_SCAN_MODE_NONE; 984 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 985 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 986 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 987 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 988 } 989 // errorLog("Incorrect scan mode in convertScanModeToHal"); 990 return -1; 991 } 992 993 static int convertScanModeFromHal(int mode) { 994 switch (mode) { 995 case AbstractionLayer.BT_SCAN_MODE_NONE: 996 return BluetoothAdapter.SCAN_MODE_NONE; 997 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 998 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 999 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 1000 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1001 } 1002 //errorLog("Incorrect scan mode in convertScanModeFromHal"); 1003 return -1; 1004 } 1005 1006 private void debugLog(String msg) { 1007 Log.d(TAG +"(" +hashCode()+")", msg); 1008 } 1009 1010 private void errorLog(String msg) { 1011 Log.e(TAG +"(" +hashCode()+")", msg); 1012 } 1013 1014 private native static void classInitNative(); 1015 private native boolean initNative(); 1016 private native void cleanupNative(); 1017 /*package*/ native boolean enableNative(); 1018 /*package*/ native boolean disableNative(); 1019 /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val); 1020 /*package*/ native boolean getAdapterPropertiesNative(); 1021 /*package*/ native boolean getAdapterPropertyNative(int type); 1022 /*package*/ native boolean setAdapterPropertyNative(int type); 1023 /*package*/ native boolean 1024 setDevicePropertyNative(byte[] address, int type, byte[] val); 1025 /*package*/ native boolean getDevicePropertyNative(byte[] address, int type); 1026 1027 /*package*/ native boolean createBondNative(byte[] address); 1028 /*package*/ native boolean removeBondNative(byte[] address); 1029 /*package*/ native boolean cancelBondNative(byte[] address); 1030 1031 private native boolean startDiscoveryNative(); 1032 private native boolean cancelDiscoveryNative(); 1033 1034 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 1035 private native boolean sspReplyNative(byte[] address, int type, boolean 1036 accept, int passkey); 1037 1038 /*package*/ native boolean getRemoteServicesNative(byte[] address); 1039 1040 // TODO(BT) move this to ../btsock dir 1041 private native int connectSocketNative(byte[] address, int type, 1042 byte[] uuid, int port, int flag); 1043 private native int createSocketChannelNative(int type, String serviceName, 1044 byte[] uuid, int port, int flag); 1045 1046 protected void finalize() { 1047 cleanup(); 1048 if (TRACE_REF) { 1049 synchronized (AdapterService.class) { 1050 sRefCount--; 1051 Log.d(TAG, "REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount); 1052 } 1053 } 1054 } 1055} 1056