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