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