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