AdapterService.java revision 4603dc081506452854023a1c6eacdfca468e0dc4
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 // TODO(BT) mAdapterStateMachine.quit(); 392 mAdapterStateMachine.cleanup(); 393 mAdapterStateMachine = null; 394 } 395 396 if (mBondStateMachine != null) { 397 // TODO(BT) 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 enableNoAutoConnect() { 565 // TODO(BT) 566 return false; 567 } 568 569 public boolean disable(boolean persist) { 570 AdapterService service = getService(); 571 if (service == null) return false; 572 return service.disable(persist); 573 } 574 575 public String getAddress() { 576 AdapterService service = getService(); 577 if (service == null) return null; 578 return service.getAddress(); 579 } 580 581 public ParcelUuid[] getUuids() { 582 AdapterService service = getService(); 583 if (service == null) return new ParcelUuid[0]; 584 return service.getUuids(); 585 } 586 587 public String getName() { 588 AdapterService service = getService(); 589 if (service == null) return null; 590 return service.getName(); 591 } 592 593 public boolean setName(String name) { 594 AdapterService service = getService(); 595 if (service == null) return false; 596 return service.setName(name); 597 } 598 599 public int getScanMode() { 600 AdapterService service = getService(); 601 if (service == null) return BluetoothAdapter.SCAN_MODE_NONE; 602 return service.getScanMode(); 603 } 604 605 public boolean setScanMode(int mode, int duration) { 606 AdapterService service = getService(); 607 if (service == null) return false; 608 return service.setScanMode(mode,duration); 609 } 610 611 public int getDiscoverableTimeout() { 612 AdapterService service = getService(); 613 if (service == null) return 0; 614 return service.getDiscoverableTimeout(); 615 } 616 617 public boolean setDiscoverableTimeout(int timeout) { 618 AdapterService service = getService(); 619 if (service == null) return false; 620 return service.setDiscoverableTimeout(timeout); 621 } 622 623 public boolean startDiscovery() { 624 AdapterService service = getService(); 625 if (service == null) return false; 626 return service.startDiscovery(); 627 } 628 629 public boolean cancelDiscovery() { 630 AdapterService service = getService(); 631 if (service == null) return false; 632 return service.cancelDiscovery(); 633 } 634 public boolean isDiscovering() { 635 AdapterService service = getService(); 636 if (service == null) return false; 637 return service.isDiscovering(); 638 } 639 640 public BluetoothDevice[] getBondedDevices() { 641 AdapterService service = getService(); 642 if (service == null) return new BluetoothDevice[0]; 643 return service.getBondedDevices(); 644 } 645 646 public int getAdapterConnectionState() { 647 AdapterService service = getService(); 648 if (service == null) return BluetoothAdapter.STATE_DISCONNECTED; 649 return service.getAdapterConnectionState(); 650 } 651 652 public int getProfileConnectionState(int profile) { 653 AdapterService service = getService(); 654 if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 655 return service.getProfileConnectionState(profile); 656 } 657 658 public boolean createBond(BluetoothDevice device) { 659 AdapterService service = getService(); 660 if (service == null) return false; 661 return service.createBond(device); 662 } 663 664 public boolean cancelBondProcess(BluetoothDevice device) { 665 AdapterService service = getService(); 666 if (service == null) return false; 667 return service.cancelBondProcess(device); 668 } 669 670 public boolean removeBond(BluetoothDevice device) { 671 AdapterService service = getService(); 672 if (service == null) return false; 673 return service.removeBond(device); 674 } 675 676 public int getBondState(BluetoothDevice device) { 677 AdapterService service = getService(); 678 if (service == null) return BluetoothDevice.BOND_NONE; 679 return service.getBondState(device); 680 } 681 682 public String getRemoteName(BluetoothDevice device) { 683 AdapterService service = getService(); 684 if (service == null) return null; 685 return service.getRemoteName(device); 686 } 687 688 public String getRemoteAlias(BluetoothDevice device) { 689 AdapterService service = getService(); 690 if (service == null) return null; 691 return service.getRemoteAlias(device); 692 } 693 694 public boolean setRemoteAlias(BluetoothDevice device, String name) { 695 AdapterService service = getService(); 696 if (service == null) return false; 697 return service.setRemoteAlias(device, name); 698 } 699 700 public int getRemoteClass(BluetoothDevice device) { 701 AdapterService service = getService(); 702 if (service == null) return 0; 703 return service.getRemoteClass(device); 704 } 705 706 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 707 AdapterService service = getService(); 708 if (service == null) return null; 709 return service.getRemoteUuids(device); 710 } 711 712 public boolean fetchRemoteUuids(BluetoothDevice device) { 713 AdapterService service = getService(); 714 if (service == null) return false; 715 return service.fetchRemoteUuids(device); 716 } 717 718 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 719 AdapterService service = getService(); 720 if (service == null) return false; 721 return service.setPin(device, accept, len, pinCode); 722 } 723 724 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 725 AdapterService service = getService(); 726 if (service == null) return false; 727 return service.setPasskey(device, accept, len, passkey); 728 } 729 730 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 731 AdapterService service = getService(); 732 if (service == null) return false; 733 return service.setPairingConfirmation(device, accept); 734 } 735 736 public void sendConnectionStateChange(BluetoothDevice 737 device, int profile, int state, int prevState) { 738 AdapterService service = getService(); 739 if (service == null) return; 740 service.sendConnectionStateChange(device, profile, state, prevState); 741 } 742 743 public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 744 ParcelUuid uuid, int port, int flag) { 745 AdapterService service = getService(); 746 if (service == null) return null; 747 return service.connectSocket(device, type, uuid, port, flag); 748 } 749 750 public ParcelFileDescriptor createSocketChannel(int type, String serviceName, 751 ParcelUuid uuid, int port, int flag) { 752 AdapterService service = getService(); 753 if (service == null) return null; 754 return service.createSocketChannel(type, serviceName, uuid, port, flag); 755 } 756 757 public void registerCallback(IBluetoothCallback cb) { 758 AdapterService service = getService(); 759 if (service == null) return ; 760 service.registerCallback(cb); 761 } 762 763 public void unregisterCallback(IBluetoothCallback cb) { 764 AdapterService service = getService(); 765 if (service == null) return ; 766 service.unregisterCallback(cb); 767 } 768 }; 769 770 771 //----API Methods-------- 772 boolean isEnabled() { 773 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 774 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 775 } 776 777 int getState() { 778 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 779 debugLog("getState(): mAdapterProperties: " + mAdapterProperties); 780 return mAdapterProperties.getState(); 781 } 782 783 boolean enable() { 784 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 785 "Need BLUETOOTH ADMIN permission"); 786 if (DBG) debugLog("enable() called..."); 787 Message m = 788 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 789 m.arg1 = 1; //persist state 790 mAdapterStateMachine.sendMessage(m); 791 return true; 792 } 793 794 boolean disable(boolean persist) { 795 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 796 "Need BLUETOOTH ADMIN permission"); 797 if (DBG) debugLog("disable() called..."); 798 int val = (persist ? 1 : 0); 799 Message m = 800 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 801 m.arg1 = val; 802 mAdapterStateMachine.sendMessage(m); 803 return true; 804 } 805 806 String getAddress() { 807 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 808 String addrString = null; 809 byte[] address = mAdapterProperties.getAddress(); 810 return Utils.getAddressStringFromByte(address); 811 } 812 813 ParcelUuid[] getUuids() { 814 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 815 return mAdapterProperties.getUuids(); 816 } 817 818 String getName() { 819 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 820 "Need BLUETOOTH permission"); 821 try { 822 return mAdapterProperties.getName(); 823 } catch (Throwable t) { 824 Log.d(TAG, "Unexpected exception while calling getName()",t); 825 } 826 return null; 827 } 828 829 boolean setName(String name) { 830 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 831 "Need BLUETOOTH ADMIN permission"); 832 return mAdapterProperties.setName(name); 833 } 834 835 int getScanMode() { 836 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 837 return mAdapterProperties.getScanMode(); 838 } 839 840 boolean setScanMode(int mode, int duration) { 841 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 842 setDiscoverableTimeout(duration); 843 844 int newMode = convertScanModeToHal(mode); 845 return mAdapterProperties.setScanMode(newMode); 846 } 847 848 int getDiscoverableTimeout() { 849 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 850 return mAdapterProperties.getDiscoverableTimeout(); 851 } 852 853 boolean setDiscoverableTimeout(int timeout) { 854 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 855 return mAdapterProperties.setDiscoverableTimeout(timeout); 856 } 857 858 boolean startDiscovery() { 859 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 860 "Need BLUETOOTH ADMIN permission"); 861 return startDiscoveryNative(); 862 } 863 864 boolean cancelDiscovery() { 865 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 866 "Need BLUETOOTH ADMIN permission"); 867 return cancelDiscoveryNative(); 868 } 869 870 boolean isDiscovering() { 871 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 872 return mAdapterProperties.isDiscovering(); 873 } 874 875 BluetoothDevice[] getBondedDevices() { 876 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 877 debugLog("Get Bonded Devices being called"); 878 return mAdapterProperties.getBondedDevices(); 879 } 880 881 int getAdapterConnectionState() { 882 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 883 return mAdapterProperties.getConnectionState(); 884 } 885 886 int getProfileConnectionState(int profile) { 887 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 888 return mAdapterProperties.getProfileConnectionState(profile); 889 } 890 891 boolean createBond(BluetoothDevice device) { 892 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 893 "Need BLUETOOTH ADMIN permission"); 894 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 895 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 896 return false; 897 } 898 899 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 900 msg.obj = device; 901 mBondStateMachine.sendMessage(msg); 902 return true; 903 } 904 905 boolean cancelBondProcess(BluetoothDevice device) { 906 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 907 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 908 return cancelBondNative(addr); 909 } 910 911 boolean removeBond(BluetoothDevice device) { 912 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 913 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 914 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 915 return false; 916 } 917 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 918 msg.obj = device; 919 mBondStateMachine.sendMessage(msg); 920 return true; 921 } 922 923 int getBondState(BluetoothDevice device) { 924 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 925 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 926 if (deviceProp == null) { 927 return BluetoothDevice.BOND_NONE; 928 } 929 return deviceProp.getBondState(); 930 } 931 932 String getRemoteName(BluetoothDevice device) { 933 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 934 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 935 if (deviceProp == null) return null; 936 return deviceProp.getName(); 937 } 938 939 String getRemoteAlias(BluetoothDevice device) { 940 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 941 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 942 if (deviceProp == null) return null; 943 return deviceProp.getAlias(); 944 } 945 946 boolean setRemoteAlias(BluetoothDevice device, String name) { 947 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 948 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 949 if (deviceProp == null) return false; 950 deviceProp.setAlias(name); 951 return true; 952 } 953 954 int getRemoteClass(BluetoothDevice device) { 955 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 956 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 957 if (deviceProp == null) return 0; 958 959 return deviceProp.getBluetoothClass(); 960 } 961 962 ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 963 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 964 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 965 if (deviceProp == null) return null; 966 return deviceProp.getUuids(); 967 } 968 969 boolean fetchRemoteUuids(BluetoothDevice device) { 970 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 971 mRemoteDevices.fetchUuids(device); 972 return true; 973 } 974 975 boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 976 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 977 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 978 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 979 return false; 980 } 981 982 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 983 return pinReplyNative(addr, accept, len, pinCode); 984 } 985 986 boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 987 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 988 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 989 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 990 return false; 991 } 992 993 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 994 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept, 995 Utils.byteArrayToInt(passkey)); 996 } 997 998 boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 999 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1000 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1001 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1002 return false; 1003 } 1004 1005 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1006 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 1007 accept, 0); 1008 } 1009 1010 void sendConnectionStateChange(BluetoothDevice 1011 device, int profile, int state, int prevState) { 1012 // TODO(BT) permission check? 1013 // Since this is a binder call check if Bluetooth is on still 1014 if (getState() == BluetoothAdapter.STATE_OFF) return; 1015 1016 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 1017 1018 } 1019 1020 ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 1021 ParcelUuid uuid, int port, int flag) { 1022 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1023 int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()), 1024 type, Utils.uuidToByteArray(uuid), port, flag); 1025 if (fd < 0) { 1026 errorLog("Failed to connect socket"); 1027 return null; 1028 } 1029 return ParcelFileDescriptor.adoptFd(fd); 1030 } 1031 1032 ParcelFileDescriptor createSocketChannel(int type, String serviceName, 1033 ParcelUuid uuid, int port, int flag) { 1034 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1035 int fd = createSocketChannelNative(type, serviceName, 1036 Utils.uuidToByteArray(uuid), port, flag); 1037 if (fd < 0) { 1038 errorLog("Failed to create socket channel"); 1039 return null; 1040 } 1041 return ParcelFileDescriptor.adoptFd(fd); 1042 } 1043 1044 void registerCallback(IBluetoothCallback cb) { 1045 mCallbacks.register(cb); 1046 } 1047 1048 void unregisterCallback(IBluetoothCallback cb) { 1049 mCallbacks.unregister(cb); 1050 } 1051 1052 private static int convertScanModeToHal(int mode) { 1053 switch (mode) { 1054 case BluetoothAdapter.SCAN_MODE_NONE: 1055 return AbstractionLayer.BT_SCAN_MODE_NONE; 1056 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 1057 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 1058 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 1059 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1060 } 1061 // errorLog("Incorrect scan mode in convertScanModeToHal"); 1062 return -1; 1063 } 1064 1065 static int convertScanModeFromHal(int mode) { 1066 switch (mode) { 1067 case AbstractionLayer.BT_SCAN_MODE_NONE: 1068 return BluetoothAdapter.SCAN_MODE_NONE; 1069 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 1070 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 1071 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 1072 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1073 } 1074 //errorLog("Incorrect scan mode in convertScanModeFromHal"); 1075 return -1; 1076 } 1077 1078 private void debugLog(String msg) { 1079 Log.d(TAG +"(" +hashCode()+")", msg); 1080 } 1081 1082 private void errorLog(String msg) { 1083 Log.e(TAG +"(" +hashCode()+")", msg); 1084 } 1085 1086 private native static void classInitNative(); 1087 private native boolean initNative(); 1088 private native void cleanupNative(); 1089 /*package*/ native boolean enableNative(); 1090 /*package*/ native boolean disableNative(); 1091 /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val); 1092 /*package*/ native boolean getAdapterPropertiesNative(); 1093 /*package*/ native boolean getAdapterPropertyNative(int type); 1094 /*package*/ native boolean setAdapterPropertyNative(int type); 1095 /*package*/ native boolean 1096 setDevicePropertyNative(byte[] address, int type, byte[] val); 1097 /*package*/ native boolean getDevicePropertyNative(byte[] address, int type); 1098 1099 /*package*/ native boolean createBondNative(byte[] address); 1100 /*package*/ native boolean removeBondNative(byte[] address); 1101 /*package*/ native boolean cancelBondNative(byte[] address); 1102 1103 private native boolean startDiscoveryNative(); 1104 private native boolean cancelDiscoveryNative(); 1105 1106 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 1107 private native boolean sspReplyNative(byte[] address, int type, boolean 1108 accept, int passkey); 1109 1110 /*package*/ native boolean getRemoteServicesNative(byte[] address); 1111 1112 // TODO(BT) move this to ../btsock dir 1113 private native int connectSocketNative(byte[] address, int type, 1114 byte[] uuid, int port, int flag); 1115 private native int createSocketChannelNative(int type, String serviceName, 1116 byte[] uuid, int port, int flag); 1117 1118 protected void finalize() { 1119 cleanup(); 1120 if (TRACE_REF) { 1121 synchronized (AdapterService.class) { 1122 sRefCount--; 1123 Log.d(TAG, "REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount); 1124 } 1125 } 1126 } 1127} 1128