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