AdapterService.java revision 57a3923845c46742ed4f03d49dbdbb6c774ccf90
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 // TODO(BT) mAdapterStateMachine.quit(); 329 mAdapterStateMachine.cleanup(); 330 mAdapterStateMachine = null; 331 } 332 333 if (mBondStateMachine != null) { 334 // TODO(BT) mBondStateMachine.quit(); 335 mBondStateMachine.cleanup(); 336 mBondStateMachine = null; 337 } 338 339 if (mRemoteDevices != null) { 340 mRemoteDevices.cleanup(); 341 mRemoteDevices = null; 342 } 343 344 if (mNativeAvailable) { 345 Log.d(TAG, "Cleaning up adapter native...."); 346 cleanupNative(); 347 Log.d(TAG, "Done cleaning up adapter native...."); 348 mNativeAvailable=false; 349 } 350 351 if (mAdapterProperties != null) { 352 mAdapterProperties.cleanup(); 353 mAdapterProperties = null; 354 } 355 356 if (mJniCallbacks != null) { 357 mJniCallbacks.cleanup(); 358 mJniCallbacks = null; 359 } 360 361 if (mProfileServicesState != null) { 362 mProfileServicesState.clear(); 363 mProfileServicesState= null; 364 } 365 366 clearAdapterService(); 367 368 if (mBinder != null) { 369 mBinder.cleanup(); 370 mBinder = null; 371 } 372 373 if (mCallbacks !=null) { 374 mCallbacks.kill(); 375 } 376 377 if (DBG)debugLog("cleanup() done"); 378 } 379 380 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1; 381 private static final int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED=20; 382 private static final int MESSAGE_SHUTDOWN= 100; 383 private static final int SHUTDOWN_TIMEOUT=2000; 384 385 private final Handler mHandler = new Handler() { 386 @Override 387 public void handleMessage(Message msg) { 388 if (DBG) debugLog("Message: " + msg.what); 389 390 switch (msg.what) { 391 case MESSAGE_SHUTDOWN: { 392 if (DBG) Log.d(TAG,"***SHUTDOWN: TIMEOUT!!! Forcing shutdown..."); 393 stopSelf(); 394 } 395 break; 396 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: { 397 if(DBG) debugLog("MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 398 processProfileServiceStateChanged((String) msg.obj, msg.arg1); 399 } 400 break; 401 case MESSAGE_PROFILE_CONNECTION_STATE_CHANGED: { 402 if (DBG) debugLog( "MESSAGE_PROFILE_CONNECTION_STATE_CHANGED"); 403 processProfileStateChanged((BluetoothDevice) msg.obj, msg.arg1,msg.arg2, msg.getData().getInt("prevState",BluetoothAdapter.ERROR)); 404 } 405 break; 406 } 407 } 408 }; 409 410 @SuppressWarnings("rawtypes") 411 private void setProfileServiceState(Class[] services, int state) { 412 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 413 Log.w(TAG,"setProfileServiceState(): invalid state...Leaving..."); 414 return; 415 } 416 417 int expectedCurrentState= BluetoothAdapter.STATE_OFF; 418 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 419 if (state == BluetoothAdapter.STATE_OFF) { 420 expectedCurrentState= BluetoothAdapter.STATE_ON; 421 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 422 } 423 424 for (int i=0; i <services.length;i++) { 425 String serviceName = services[i].getName(); 426 Integer serviceState = mProfileServicesState.get(serviceName); 427 if(serviceState != null && serviceState != expectedCurrentState) { 428 Log.w(TAG, "Unable to " + (state == BluetoothAdapter.STATE_OFF? "start" : "stop" ) +" service " + 429 serviceName+". Invalid state: " + serviceState); 430 continue; 431 } 432 433 if (DBG) { 434 Log.w(TAG, (state == BluetoothAdapter.STATE_OFF? "Stopping" : "Starting" ) +" service " + 435 serviceName); 436 } 437 438 mProfileServicesState.put(serviceName,pendingState); 439 Intent intent = new Intent(this,services[i]); 440 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); 441 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); 442 startService(intent); 443 } 444 } 445 446 private boolean isAvailable() { 447 return !mCleaningUp; 448 } 449 450 /** 451 * Handlers for incoming service calls 452 */ 453 private AdapterServiceBinder mBinder; 454 455 /** 456 * The Binder implementation must be declared to be a static class, with 457 * the AdapterService instance passed in the constructor. Furthermore, 458 * when the AdapterService shuts down, the reference to the AdapterService 459 * must be explicitly removed. 460 * 461 * Otherwise, a memory leak can occur from repeated starting/stopping the 462 * service...Please refer to android.os.Binder for further details on 463 * why an inner instance class should be avoided. 464 * 465 */ 466 private static class AdapterServiceBinder extends IBluetooth.Stub { 467 private AdapterService mService; 468 469 public AdapterServiceBinder(AdapterService svc) { 470 mService = svc; 471 } 472 public boolean cleanup() { 473 mService = null; 474 return true; 475 } 476 477 public AdapterService getService() { 478 if (mService != null && mService.isAvailable()) { 479 return mService; 480 } 481 return null; 482 } 483 public boolean isEnabled() { 484 AdapterService service = getService(); 485 if (service == null) return false; 486 return service.isEnabled(); 487 } 488 489 public int getState() { 490 AdapterService service = getService(); 491 if (service == null) return BluetoothAdapter.STATE_OFF; 492 return service.getState(); 493 } 494 495 public boolean enable() { 496 AdapterService service = getService(); 497 if (service == null) return false; 498 return service.enable(); 499 } 500 501 public boolean enableNoAutoConnect() { 502 // TODO(BT) 503 return false; 504 } 505 506 public boolean disable() { 507 AdapterService service = getService(); 508 if (service == null) return false; 509 return service.disable(); 510 } 511 512 public String getAddress() { 513 AdapterService service = getService(); 514 if (service == null) return null; 515 return service.getAddress(); 516 } 517 518 public ParcelUuid[] getUuids() { 519 AdapterService service = getService(); 520 if (service == null) return new ParcelUuid[0]; 521 return service.getUuids(); 522 } 523 524 public String getName() { 525 AdapterService service = getService(); 526 if (service == null) return null; 527 return service.getName(); 528 } 529 530 public boolean setName(String name) { 531 AdapterService service = getService(); 532 if (service == null) return false; 533 return service.setName(name); 534 } 535 536 public int getScanMode() { 537 AdapterService service = getService(); 538 if (service == null) return BluetoothAdapter.SCAN_MODE_NONE; 539 return service.getScanMode(); 540 } 541 542 public boolean setScanMode(int mode, int duration) { 543 AdapterService service = getService(); 544 if (service == null) return false; 545 return service.setScanMode(mode,duration); 546 } 547 548 public int getDiscoverableTimeout() { 549 AdapterService service = getService(); 550 if (service == null) return 0; 551 return service.getDiscoverableTimeout(); 552 } 553 554 public boolean setDiscoverableTimeout(int timeout) { 555 AdapterService service = getService(); 556 if (service == null) return false; 557 return service.setDiscoverableTimeout(timeout); 558 } 559 560 public boolean startDiscovery() { 561 AdapterService service = getService(); 562 if (service == null) return false; 563 return service.startDiscovery(); 564 } 565 566 public boolean cancelDiscovery() { 567 AdapterService service = getService(); 568 if (service == null) return false; 569 return service.cancelDiscovery(); 570 } 571 public boolean isDiscovering() { 572 AdapterService service = getService(); 573 if (service == null) return false; 574 return service.isDiscovering(); 575 } 576 577 public BluetoothDevice[] getBondedDevices() { 578 AdapterService service = getService(); 579 if (service == null) return new BluetoothDevice[0]; 580 return service.getBondedDevices(); 581 } 582 583 public int getAdapterConnectionState() { 584 AdapterService service = getService(); 585 if (service == null) return BluetoothAdapter.STATE_DISCONNECTED; 586 return service.getAdapterConnectionState(); 587 } 588 589 public int getProfileConnectionState(int profile) { 590 AdapterService service = getService(); 591 if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 592 return service.getProfileConnectionState(profile); 593 } 594 595 public boolean createBond(BluetoothDevice device) { 596 AdapterService service = getService(); 597 if (service == null) return false; 598 return service.createBond(device); 599 } 600 601 public boolean cancelBondProcess(BluetoothDevice device) { 602 AdapterService service = getService(); 603 if (service == null) return false; 604 return service.cancelBondProcess(device); 605 } 606 607 public boolean removeBond(BluetoothDevice device) { 608 AdapterService service = getService(); 609 if (service == null) return false; 610 return service.removeBond(device); 611 } 612 613 public int getBondState(BluetoothDevice device) { 614 AdapterService service = getService(); 615 if (service == null) return BluetoothDevice.BOND_NONE; 616 return service.getBondState(device); 617 } 618 619 public String getRemoteName(BluetoothDevice device) { 620 AdapterService service = getService(); 621 if (service == null) return null; 622 return service.getRemoteName(device); 623 } 624 625 public String getRemoteAlias(BluetoothDevice device) { 626 AdapterService service = getService(); 627 if (service == null) return null; 628 return service.getRemoteAlias(device); 629 } 630 631 public boolean setRemoteAlias(BluetoothDevice device, String name) { 632 AdapterService service = getService(); 633 if (service == null) return false; 634 return service.setRemoteAlias(device, name); 635 } 636 637 public int getRemoteClass(BluetoothDevice device) { 638 AdapterService service = getService(); 639 if (service == null) return 0; 640 return service.getRemoteClass(device); 641 } 642 643 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 644 AdapterService service = getService(); 645 if (service == null) return null; 646 return service.getRemoteUuids(device); 647 } 648 649 public boolean fetchRemoteUuids(BluetoothDevice device) { 650 AdapterService service = getService(); 651 if (service == null) return false; 652 return service.fetchRemoteUuids(device); 653 } 654 655 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 656 AdapterService service = getService(); 657 if (service == null) return false; 658 return service.setPin(device, accept, len, pinCode); 659 } 660 661 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 662 AdapterService service = getService(); 663 if (service == null) return false; 664 return service.setPasskey(device, accept, len, passkey); 665 } 666 667 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 668 AdapterService service = getService(); 669 if (service == null) return false; 670 return service.setPairingConfirmation(device, accept); 671 } 672 673 public void sendConnectionStateChange(BluetoothDevice 674 device, int profile, int state, int prevState) { 675 AdapterService service = getService(); 676 if (service == null) return; 677 service.sendConnectionStateChange(device, profile, state, prevState); 678 } 679 680 public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 681 ParcelUuid uuid, int port, int flag) { 682 AdapterService service = getService(); 683 if (service == null) return null; 684 return service.connectSocket(device, type, uuid, port, flag); 685 } 686 687 public ParcelFileDescriptor createSocketChannel(int type, String serviceName, 688 ParcelUuid uuid, int port, int flag) { 689 AdapterService service = getService(); 690 if (service == null) return null; 691 return service.createSocketChannel(type, serviceName, uuid, port, flag); 692 } 693 694 public void registerCallback(IBluetoothCallback cb) { 695 AdapterService service = getService(); 696 if (service == null) return ; 697 service.registerCallback(cb); 698 } 699 700 public void unregisterCallback(IBluetoothCallback cb) { 701 AdapterService service = getService(); 702 if (service == null) return ; 703 service.unregisterCallback(cb); 704 } 705 }; 706 707 708 //----API Methods-------- 709 boolean isEnabled() { 710 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 711 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 712 } 713 714 int getState() { 715 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 716 debugLog("getState(): mAdapterProperties: " + mAdapterProperties); 717 return mAdapterProperties.getState(); 718 } 719 720 boolean enable() { 721 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 722 "Need BLUETOOTH ADMIN permission"); 723 if (DBG) debugLog("enable() called..."); 724 Message m = 725 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 726 mAdapterStateMachine.sendMessage(m); 727 return true; 728 } 729 730 boolean disable() { 731 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 732 "Need BLUETOOTH ADMIN permission"); 733 if (DBG) debugLog("disable() called..."); 734 Message m = 735 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 736 mAdapterStateMachine.sendMessage(m); 737 return true; 738 } 739 740 String getAddress() { 741 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 742 String addrString = null; 743 byte[] address = mAdapterProperties.getAddress(); 744 return Utils.getAddressStringFromByte(address); 745 } 746 747 ParcelUuid[] getUuids() { 748 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 749 return mAdapterProperties.getUuids(); 750 } 751 752 String getName() { 753 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 754 "Need BLUETOOTH permission"); 755 try { 756 return mAdapterProperties.getName(); 757 } catch (Throwable t) { 758 Log.d(TAG, "Unexpected exception while calling getName()",t); 759 } 760 return null; 761 } 762 763 boolean setName(String name) { 764 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 765 "Need BLUETOOTH ADMIN permission"); 766 return mAdapterProperties.setName(name); 767 } 768 769 int getScanMode() { 770 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 771 return mAdapterProperties.getScanMode(); 772 } 773 774 boolean setScanMode(int mode, int duration) { 775 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 776 setDiscoverableTimeout(duration); 777 778 int newMode = convertScanModeToHal(mode); 779 return mAdapterProperties.setScanMode(newMode); 780 } 781 782 int getDiscoverableTimeout() { 783 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 784 return mAdapterProperties.getDiscoverableTimeout(); 785 } 786 787 boolean setDiscoverableTimeout(int timeout) { 788 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 789 return mAdapterProperties.setDiscoverableTimeout(timeout); 790 } 791 792 boolean startDiscovery() { 793 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 794 "Need BLUETOOTH ADMIN permission"); 795 return startDiscoveryNative(); 796 } 797 798 boolean cancelDiscovery() { 799 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 800 "Need BLUETOOTH ADMIN permission"); 801 return cancelDiscoveryNative(); 802 } 803 804 boolean isDiscovering() { 805 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 806 return mAdapterProperties.isDiscovering(); 807 } 808 809 BluetoothDevice[] getBondedDevices() { 810 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 811 debugLog("Get Bonded Devices being called"); 812 return mAdapterProperties.getBondedDevices(); 813 } 814 815 int getAdapterConnectionState() { 816 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 817 return mAdapterProperties.getConnectionState(); 818 } 819 820 int getProfileConnectionState(int profile) { 821 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 822 return mAdapterProperties.getProfileConnectionState(profile); 823 } 824 825 boolean createBond(BluetoothDevice device) { 826 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 827 "Need BLUETOOTH ADMIN permission"); 828 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 829 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 830 return false; 831 } 832 833 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 834 msg.obj = device; 835 mBondStateMachine.sendMessage(msg); 836 return true; 837 } 838 839 boolean cancelBondProcess(BluetoothDevice device) { 840 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 841 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 842 return cancelBondNative(addr); 843 } 844 845 boolean removeBond(BluetoothDevice device) { 846 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 847 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 848 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 849 return false; 850 } 851 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 852 msg.obj = device; 853 mBondStateMachine.sendMessage(msg); 854 return true; 855 } 856 857 int getBondState(BluetoothDevice device) { 858 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 859 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 860 if (deviceProp == null) { 861 return BluetoothDevice.BOND_NONE; 862 } 863 return deviceProp.getBondState(); 864 } 865 866 String getRemoteName(BluetoothDevice device) { 867 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 868 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 869 if (deviceProp == null) return null; 870 return deviceProp.getName(); 871 } 872 873 String getRemoteAlias(BluetoothDevice device) { 874 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 875 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 876 if (deviceProp == null) return null; 877 return deviceProp.getAlias(); 878 } 879 880 boolean setRemoteAlias(BluetoothDevice device, String name) { 881 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 882 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 883 if (deviceProp == null) return false; 884 deviceProp.setAlias(name); 885 return true; 886 } 887 888 int getRemoteClass(BluetoothDevice device) { 889 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 890 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 891 if (deviceProp == null) return 0; 892 893 return deviceProp.getBluetoothClass(); 894 } 895 896 ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 897 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 898 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 899 if (deviceProp == null) return null; 900 return deviceProp.getUuids(); 901 } 902 903 boolean fetchRemoteUuids(BluetoothDevice device) { 904 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 905 mRemoteDevices.fetchUuids(device); 906 return true; 907 } 908 909 boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 910 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 911 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 912 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 913 return false; 914 } 915 916 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 917 return pinReplyNative(addr, accept, len, pinCode); 918 } 919 920 boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 921 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 922 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 923 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 924 return false; 925 } 926 927 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 928 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept, 929 Utils.byteArrayToInt(passkey)); 930 } 931 932 boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 933 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 934 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 935 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 936 return false; 937 } 938 939 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 940 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 941 accept, 0); 942 } 943 944 void sendConnectionStateChange(BluetoothDevice 945 device, int profile, int state, int prevState) { 946 // TODO(BT) permission check? 947 // Since this is a binder call check if Bluetooth is on still 948 if (getState() == BluetoothAdapter.STATE_OFF) return; 949 950 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 951 952 } 953 954 ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 955 ParcelUuid uuid, int port, int flag) { 956 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 957 int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()), 958 type, Utils.uuidToByteArray(uuid), port, flag); 959 if (fd < 0) { 960 errorLog("Failed to connect socket"); 961 return null; 962 } 963 return ParcelFileDescriptor.adoptFd(fd); 964 } 965 966 ParcelFileDescriptor createSocketChannel(int type, String serviceName, 967 ParcelUuid uuid, int port, int flag) { 968 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 969 int fd = createSocketChannelNative(type, serviceName, 970 Utils.uuidToByteArray(uuid), port, flag); 971 if (fd < 0) { 972 errorLog("Failed to create socket channel"); 973 return null; 974 } 975 return ParcelFileDescriptor.adoptFd(fd); 976 } 977 978 void registerCallback(IBluetoothCallback cb) { 979 mCallbacks.register(cb); 980 } 981 982 void unregisterCallback(IBluetoothCallback cb) { 983 mCallbacks.unregister(cb); 984 } 985 986 private static int convertScanModeToHal(int mode) { 987 switch (mode) { 988 case BluetoothAdapter.SCAN_MODE_NONE: 989 return AbstractionLayer.BT_SCAN_MODE_NONE; 990 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 991 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 992 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 993 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 994 } 995 // errorLog("Incorrect scan mode in convertScanModeToHal"); 996 return -1; 997 } 998 999 static int convertScanModeFromHal(int mode) { 1000 switch (mode) { 1001 case AbstractionLayer.BT_SCAN_MODE_NONE: 1002 return BluetoothAdapter.SCAN_MODE_NONE; 1003 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 1004 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 1005 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 1006 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1007 } 1008 //errorLog("Incorrect scan mode in convertScanModeFromHal"); 1009 return -1; 1010 } 1011 1012 private void debugLog(String msg) { 1013 Log.d(TAG +"(" +hashCode()+")", msg); 1014 } 1015 1016 private void errorLog(String msg) { 1017 Log.e(TAG +"(" +hashCode()+")", msg); 1018 } 1019 1020 private native static void classInitNative(); 1021 private native boolean initNative(); 1022 private native void cleanupNative(); 1023 /*package*/ native boolean enableNative(); 1024 /*package*/ native boolean disableNative(); 1025 /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val); 1026 /*package*/ native boolean getAdapterPropertiesNative(); 1027 /*package*/ native boolean getAdapterPropertyNative(int type); 1028 /*package*/ native boolean setAdapterPropertyNative(int type); 1029 /*package*/ native boolean 1030 setDevicePropertyNative(byte[] address, int type, byte[] val); 1031 /*package*/ native boolean getDevicePropertyNative(byte[] address, int type); 1032 1033 /*package*/ native boolean createBondNative(byte[] address); 1034 /*package*/ native boolean removeBondNative(byte[] address); 1035 /*package*/ native boolean cancelBondNative(byte[] address); 1036 1037 private native boolean startDiscoveryNative(); 1038 private native boolean cancelDiscoveryNative(); 1039 1040 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 1041 private native boolean sspReplyNative(byte[] address, int type, boolean 1042 accept, int passkey); 1043 1044 /*package*/ native boolean getRemoteServicesNative(byte[] address); 1045 1046 // TODO(BT) move this to ../btsock dir 1047 private native int connectSocketNative(byte[] address, int type, 1048 byte[] uuid, int port, int flag); 1049 private native int createSocketChannelNative(int type, String serviceName, 1050 byte[] uuid, int port, int flag); 1051 1052 protected void finalize() { 1053 cleanup(); 1054 if (TRACE_REF) { 1055 synchronized (AdapterService.class) { 1056 sRefCount--; 1057 Log.d(TAG, "REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount); 1058 } 1059 } 1060 } 1061} 1062