AdapterService.java revision bd704c741b8c523ad747214f6f0520ac3e2caf8f
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 = false; 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 // don't check caller, may be called from system UI 487 AdapterService service = getService(); 488 if (service == null) return false; 489 return service.isEnabled(); 490 } 491 492 public int getState() { 493 // don't check caller, may be called from system UI 494 AdapterService service = getService(); 495 if (service == null) return BluetoothAdapter.STATE_OFF; 496 return service.getState(); 497 } 498 499 public boolean enable() { 500 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 501 (!Utils.checkCaller())) { 502 Log.w(TAG,"enable(): not allowed for non-active user and non system user"); 503 return false; 504 } 505 506 AdapterService service = getService(); 507 if (service == null) return false; 508 return service.enable(); 509 } 510 511 public boolean enableNoAutoConnect() { 512 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 513 (!Utils.checkCaller())) { 514 Log.w(TAG,"enableNoAuto(): not allowed for non-active user and non system user"); 515 return false; 516 } 517 518 AdapterService service = getService(); 519 if (service == null) return false; 520 return service.enableNoAutoConnect(); 521 } 522 523 public boolean disable() { 524 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 525 (!Utils.checkCaller())) { 526 Log.w(TAG,"disable(): not allowed for non-active user and non system user"); 527 return false; 528 } 529 530 AdapterService service = getService(); 531 if (service == null) return false; 532 return service.disable(); 533 } 534 535 public String getAddress() { 536 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 537 (!Utils.checkCaller())) { 538 Log.w(TAG,"getAddress(): not allowed for non-active user and non system user"); 539 return null; 540 } 541 542 AdapterService service = getService(); 543 if (service == null) return null; 544 return service.getAddress(); 545 } 546 547 public ParcelUuid[] getUuids() { 548 if (!Utils.checkCaller()) { 549 Log.w(TAG,"getUuids(): not allowed for non-active user"); 550 return new ParcelUuid[0]; 551 } 552 553 AdapterService service = getService(); 554 if (service == null) return new ParcelUuid[0]; 555 return service.getUuids(); 556 } 557 558 public String getName() { 559 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 560 (!Utils.checkCaller())) { 561 Log.w(TAG,"getName(): not allowed for non-active user and non system user"); 562 return null; 563 } 564 565 AdapterService service = getService(); 566 if (service == null) return null; 567 return service.getName(); 568 } 569 570 public boolean setName(String name) { 571 if (!Utils.checkCaller()) { 572 Log.w(TAG,"setName(): not allowed for non-active user"); 573 return false; 574 } 575 576 AdapterService service = getService(); 577 if (service == null) return false; 578 return service.setName(name); 579 } 580 581 public int getScanMode() { 582 if (!Utils.checkCaller()) { 583 Log.w(TAG,"getScanMode(): not allowed for non-active user"); 584 return BluetoothAdapter.SCAN_MODE_NONE; 585 } 586 587 AdapterService service = getService(); 588 if (service == null) return BluetoothAdapter.SCAN_MODE_NONE; 589 return service.getScanMode(); 590 } 591 592 public boolean setScanMode(int mode, int duration) { 593 if (!Utils.checkCaller()) { 594 Log.w(TAG,"setScanMode(): not allowed for non-active user"); 595 return false; 596 } 597 598 AdapterService service = getService(); 599 if (service == null) return false; 600 return service.setScanMode(mode,duration); 601 } 602 603 public int getDiscoverableTimeout() { 604 if (!Utils.checkCaller()) { 605 Log.w(TAG,"getDiscoverableTimeout(): not allowed for non-active user"); 606 return 0; 607 } 608 609 AdapterService service = getService(); 610 if (service == null) return 0; 611 return service.getDiscoverableTimeout(); 612 } 613 614 public boolean setDiscoverableTimeout(int timeout) { 615 if (!Utils.checkCaller()) { 616 Log.w(TAG,"setDiscoverableTimeout(): not allowed for non-active user"); 617 return false; 618 } 619 620 AdapterService service = getService(); 621 if (service == null) return false; 622 return service.setDiscoverableTimeout(timeout); 623 } 624 625 public boolean startDiscovery() { 626 if (!Utils.checkCaller()) { 627 Log.w(TAG,"startDiscovery(): not allowed for non-active user"); 628 return false; 629 } 630 631 AdapterService service = getService(); 632 if (service == null) return false; 633 return service.startDiscovery(); 634 } 635 636 public boolean cancelDiscovery() { 637 if (!Utils.checkCaller()) { 638 Log.w(TAG,"cancelDiscovery(): not allowed for non-active user"); 639 return false; 640 } 641 642 AdapterService service = getService(); 643 if (service == null) return false; 644 return service.cancelDiscovery(); 645 } 646 public boolean isDiscovering() { 647 if (!Utils.checkCaller()) { 648 Log.w(TAG,"isDiscovering(): not allowed for non-active user"); 649 return false; 650 } 651 652 AdapterService service = getService(); 653 if (service == null) return false; 654 return service.isDiscovering(); 655 } 656 657 public BluetoothDevice[] getBondedDevices() { 658 // don't check caller, may be called from system UI 659 AdapterService service = getService(); 660 if (service == null) return new BluetoothDevice[0]; 661 return service.getBondedDevices(); 662 } 663 664 public int getAdapterConnectionState() { 665 // don't check caller, may be called from system UI 666 AdapterService service = getService(); 667 if (service == null) return BluetoothAdapter.STATE_DISCONNECTED; 668 return service.getAdapterConnectionState(); 669 } 670 671 public int getProfileConnectionState(int profile) { 672 if (!Utils.checkCaller()) { 673 Log.w(TAG,"getProfileConnectionState: not allowed for non-active user"); 674 return BluetoothProfile.STATE_DISCONNECTED; 675 } 676 677 AdapterService service = getService(); 678 if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 679 return service.getProfileConnectionState(profile); 680 } 681 682 public boolean createBond(BluetoothDevice device) { 683 if (!Utils.checkCaller()) { 684 Log.w(TAG,"createBond(): not allowed for non-active user"); 685 return false; 686 } 687 688 AdapterService service = getService(); 689 if (service == null) return false; 690 return service.createBond(device); 691 } 692 693 public boolean cancelBondProcess(BluetoothDevice device) { 694 if (!Utils.checkCaller()) { 695 Log.w(TAG,"cancelBondProcess(): not allowed for non-active user"); 696 return false; 697 } 698 699 AdapterService service = getService(); 700 if (service == null) return false; 701 return service.cancelBondProcess(device); 702 } 703 704 public boolean removeBond(BluetoothDevice device) { 705 if (!Utils.checkCaller()) { 706 Log.w(TAG,"removeBond(): not allowed for non-active user"); 707 return false; 708 } 709 710 AdapterService service = getService(); 711 if (service == null) return false; 712 return service.removeBond(device); 713 } 714 715 public int getBondState(BluetoothDevice device) { 716 // don't check caller, may be called from system UI 717 AdapterService service = getService(); 718 if (service == null) return BluetoothDevice.BOND_NONE; 719 return service.getBondState(device); 720 } 721 722 public String getRemoteName(BluetoothDevice device) { 723 if (!Utils.checkCaller()) { 724 Log.w(TAG,"getRemoteName(): not allowed for non-active user"); 725 return null; 726 } 727 728 AdapterService service = getService(); 729 if (service == null) return null; 730 return service.getRemoteName(device); 731 } 732 733 public String getRemoteAlias(BluetoothDevice device) { 734 if (!Utils.checkCaller()) { 735 Log.w(TAG,"getRemoteAlias(): not allowed for non-active user"); 736 return null; 737 } 738 739 AdapterService service = getService(); 740 if (service == null) return null; 741 return service.getRemoteAlias(device); 742 } 743 744 public boolean setRemoteAlias(BluetoothDevice device, String name) { 745 if (!Utils.checkCaller()) { 746 Log.w(TAG,"setRemoteAlias(): not allowed for non-active user"); 747 return false; 748 } 749 750 AdapterService service = getService(); 751 if (service == null) return false; 752 return service.setRemoteAlias(device, name); 753 } 754 755 public int getRemoteClass(BluetoothDevice device) { 756 if (!Utils.checkCaller()) { 757 Log.w(TAG,"getRemoteClass(): not allowed for non-active user"); 758 return 0; 759 } 760 761 AdapterService service = getService(); 762 if (service == null) return 0; 763 return service.getRemoteClass(device); 764 } 765 766 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 767 if (!Utils.checkCaller()) { 768 Log.w(TAG,"getRemoteUuids(): not allowed for non-active user"); 769 return new ParcelUuid[0]; 770 } 771 772 AdapterService service = getService(); 773 if (service == null) return new ParcelUuid[0]; 774 return service.getRemoteUuids(device); 775 } 776 777 public boolean fetchRemoteUuids(BluetoothDevice device) { 778 if (!Utils.checkCaller()) { 779 Log.w(TAG,"fetchRemoteUuids(): not allowed for non-active user"); 780 return false; 781 } 782 783 AdapterService service = getService(); 784 if (service == null) return false; 785 return service.fetchRemoteUuids(device); 786 } 787 788 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 789 if (!Utils.checkCaller()) { 790 Log.w(TAG,"setPin(): not allowed for non-active user"); 791 return false; 792 } 793 794 AdapterService service = getService(); 795 if (service == null) return false; 796 return service.setPin(device, accept, len, pinCode); 797 } 798 799 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 800 if (!Utils.checkCaller()) { 801 Log.w(TAG,"setPasskey(): not allowed for non-active user"); 802 return false; 803 } 804 805 AdapterService service = getService(); 806 if (service == null) return false; 807 return service.setPasskey(device, accept, len, passkey); 808 } 809 810 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 811 if (!Utils.checkCaller()) { 812 Log.w(TAG,"setPairingConfirmation(): not allowed for non-active user"); 813 return false; 814 } 815 816 AdapterService service = getService(); 817 if (service == null) return false; 818 return service.setPairingConfirmation(device, accept); 819 } 820 821 public void sendConnectionStateChange(BluetoothDevice 822 device, int profile, int state, int prevState) { 823 AdapterService service = getService(); 824 if (service == null) return; 825 service.sendConnectionStateChange(device, profile, state, prevState); 826 } 827 828 public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 829 ParcelUuid uuid, int port, int flag) { 830 if (!Utils.checkCaller()) { 831 Log.w(TAG,"connectSocket(): not allowed for non-active user"); 832 return null; 833 } 834 835 AdapterService service = getService(); 836 if (service == null) return null; 837 return service.connectSocket(device, type, uuid, port, flag); 838 } 839 840 public ParcelFileDescriptor createSocketChannel(int type, String serviceName, 841 ParcelUuid uuid, int port, int flag) { 842 if (!Utils.checkCaller()) { 843 Log.w(TAG,"createSocketChannel(): not allowed for non-active user"); 844 return null; 845 } 846 847 AdapterService service = getService(); 848 if (service == null) return null; 849 return service.createSocketChannel(type, serviceName, uuid, port, flag); 850 } 851 852 public void registerCallback(IBluetoothCallback cb) { 853 AdapterService service = getService(); 854 if (service == null) return ; 855 service.registerCallback(cb); 856 } 857 858 public void unregisterCallback(IBluetoothCallback cb) { 859 AdapterService service = getService(); 860 if (service == null) return ; 861 service.unregisterCallback(cb); 862 } 863 }; 864 865 866 //----API Methods-------- 867 boolean isEnabled() { 868 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 869 870 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 871 } 872 873 int getState() { 874 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 875 876 if (mAdapterProperties == null){ 877 return BluetoothAdapter.STATE_OFF; 878 } 879 else { 880 debugLog("getState(): mAdapterProperties: " + mAdapterProperties); 881 return mAdapterProperties.getState(); 882 } 883 } 884 885 boolean enable() { 886 return enable (false); 887 } 888 889 public boolean enableNoAutoConnect() { 890 return enable (true); 891 } 892 893 public synchronized boolean enable(boolean quietMode) { 894 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 895 "Need BLUETOOTH ADMIN permission"); 896 if (DBG)debugLog("Enable called with quiet mode status = " + mQuietmode); 897 mQuietmode = quietMode; 898 Message m = 899 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 900 mAdapterStateMachine.sendMessage(m); 901 return true; 902 } 903 904 boolean disable() { 905 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 906 "Need BLUETOOTH ADMIN permission"); 907 908 if (DBG) debugLog("disable() called..."); 909 Message m = 910 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 911 mAdapterStateMachine.sendMessage(m); 912 return true; 913 } 914 915 String getAddress() { 916 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 917 918 String addrString = null; 919 byte[] address = mAdapterProperties.getAddress(); 920 return Utils.getAddressStringFromByte(address); 921 } 922 923 ParcelUuid[] getUuids() { 924 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 925 926 return mAdapterProperties.getUuids(); 927 } 928 929 String getName() { 930 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 931 "Need BLUETOOTH permission"); 932 933 try { 934 return mAdapterProperties.getName(); 935 } catch (Throwable t) { 936 Log.d(TAG, "Unexpected exception while calling getName()",t); 937 } 938 return null; 939 } 940 941 boolean setName(String name) { 942 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 943 "Need BLUETOOTH ADMIN permission"); 944 945 return mAdapterProperties.setName(name); 946 } 947 948 int getScanMode() { 949 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 950 951 return mAdapterProperties.getScanMode(); 952 } 953 954 boolean setScanMode(int mode, int duration) { 955 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 956 957 setDiscoverableTimeout(duration); 958 959 int newMode = convertScanModeToHal(mode); 960 return mAdapterProperties.setScanMode(newMode); 961 } 962 963 int getDiscoverableTimeout() { 964 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 965 966 return mAdapterProperties.getDiscoverableTimeout(); 967 } 968 969 boolean setDiscoverableTimeout(int timeout) { 970 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 971 972 return mAdapterProperties.setDiscoverableTimeout(timeout); 973 } 974 975 boolean startDiscovery() { 976 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 977 "Need BLUETOOTH ADMIN permission"); 978 979 return startDiscoveryNative(); 980 } 981 982 boolean cancelDiscovery() { 983 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 984 "Need BLUETOOTH ADMIN permission"); 985 986 return cancelDiscoveryNative(); 987 } 988 989 boolean isDiscovering() { 990 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 991 992 return mAdapterProperties.isDiscovering(); 993 } 994 995 BluetoothDevice[] getBondedDevices() { 996 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 997 debugLog("Get Bonded Devices being called"); 998 return mAdapterProperties.getBondedDevices(); 999 } 1000 1001 int getAdapterConnectionState() { 1002 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1003 1004 return mAdapterProperties.getConnectionState(); 1005 } 1006 1007 int getProfileConnectionState(int profile) { 1008 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1009 1010 return mAdapterProperties.getProfileConnectionState(profile); 1011 } 1012 1013 boolean createBond(BluetoothDevice device) { 1014 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1015 "Need BLUETOOTH ADMIN permission"); 1016 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1017 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 1018 return false; 1019 } 1020 1021 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 1022 msg.obj = device; 1023 mBondStateMachine.sendMessage(msg); 1024 return true; 1025 } 1026 1027 public boolean isQuietModeEnabled() { 1028 if (DBG) debugLog("Quiet mode Enabled = " + mQuietmode); 1029 return mQuietmode; 1030 } 1031 1032 public void autoConnect(){ 1033 if (getState() != BluetoothAdapter.STATE_ON){ 1034 errorLog("BT is not ON. Exiting autoConnect"); 1035 return; 1036 } 1037 if (isQuietModeEnabled() == false) { 1038 if (DBG) debugLog( "Initiate auto connection on BT on..."); 1039 autoConnectHeadset(); 1040 autoConnectA2dp(); 1041 } 1042 else { 1043 if (DBG) debugLog( "BT is in Quiet mode. Not initiating auto connections"); 1044 } 1045 } 1046 1047 private void autoConnectHeadset(){ 1048 HeadsetService hsService = HeadsetService.getHeadsetService(); 1049 1050 BluetoothDevice bondedDevices[] = getBondedDevices(); 1051 if ((bondedDevices == null) ||(hsService == null)) { 1052 return; 1053 } 1054 for (BluetoothDevice device : bondedDevices) { 1055 if (hsService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){ 1056 Log.d(TAG,"Auto Connecting Headset Profile with device " + device.toString()); 1057 hsService.connect(device); 1058 } 1059 } 1060 } 1061 1062 private void autoConnectA2dp(){ 1063 A2dpService a2dpSservice = A2dpService.getA2dpService(); 1064 BluetoothDevice bondedDevices[] = getBondedDevices(); 1065 if ((bondedDevices == null) ||(a2dpSservice == null)) { 1066 return; 1067 } 1068 for (BluetoothDevice device : bondedDevices) { 1069 if (a2dpSservice.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){ 1070 Log.d(TAG,"Auto Connecting A2DP Profile with device " + device.toString()); 1071 a2dpSservice.connect(device); 1072 } 1073 } 1074 } 1075 1076 public void connectOtherProfile(BluetoothDevice device, int firstProfileStatus){ 1077 if ((mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES) == false) && 1078 (isQuietModeEnabled()== false)){ 1079 Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES); 1080 m.obj = device; 1081 m.arg1 = (int)firstProfileStatus; 1082 mHandler.sendMessageDelayed(m,CONNECT_OTHER_PROFILES_TIMEOUT); 1083 } 1084 } 1085 1086 private void processConnectOtherProfiles (BluetoothDevice device, int firstProfileStatus){ 1087 if (getState()!= BluetoothAdapter.STATE_ON){ 1088 return; 1089 } 1090 HeadsetService hsService = HeadsetService.getHeadsetService(); 1091 A2dpService a2dpService = A2dpService.getA2dpService(); 1092 // if any of the profile service is null, second profile connection not required 1093 if ((hsService == null) ||(a2dpService == null )){ 1094 return; 1095 } 1096 List<BluetoothDevice> a2dpConnDevList= a2dpService.getConnectedDevices(); 1097 List<BluetoothDevice> hfConnDevList= hsService.getConnectedDevices(); 1098 // Check if the device is in disconnected state and if so return 1099 // We ned to connect other profile only if one of the profile is still in connected state 1100 // This is required to avoide a race condition in which profiles would 1101 // automaticlly connect if the disconnection is initiated within 6 seconds of connection 1102 //First profile connection being rejected is an exception 1103 if((hfConnDevList.isEmpty() && a2dpConnDevList.isEmpty())&& 1104 (PROFILE_CONN_CONNECTED == firstProfileStatus)){ 1105 return; 1106 } 1107 if((hfConnDevList.isEmpty()) && 1108 (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){ 1109 hsService.connect(device); 1110 } 1111 else if((a2dpConnDevList.isEmpty()) && 1112 (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){ 1113 a2dpService.connect(device); 1114 } 1115 } 1116 1117 private void adjustOtherHeadsetPriorities(HeadsetService hsService, 1118 BluetoothDevice connectedDevice) { 1119 for (BluetoothDevice device : getBondedDevices()) { 1120 if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && 1121 !device.equals(connectedDevice)) { 1122 hsService.setPriority(device, BluetoothProfile.PRIORITY_ON); 1123 } 1124 } 1125 } 1126 1127 private void adjustOtherSinkPriorities(A2dpService a2dpService, 1128 BluetoothDevice connectedDevice) { 1129 for (BluetoothDevice device : getBondedDevices()) { 1130 if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && 1131 !device.equals(connectedDevice)) { 1132 a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON); 1133 } 1134 } 1135 } 1136 1137 void setProfileAutoConnectionPriority (BluetoothDevice device, int profileId){ 1138 if (profileId == BluetoothProfile.HEADSET) { 1139 HeadsetService hsService = HeadsetService.getHeadsetService(); 1140 if ((hsService != null) && 1141 (BluetoothProfile.PRIORITY_AUTO_CONNECT != hsService.getPriority(device))){ 1142 adjustOtherHeadsetPriorities(hsService, device); 1143 hsService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT); 1144 } 1145 } 1146 else if (profileId == BluetoothProfile.A2DP) { 1147 A2dpService a2dpService = A2dpService.getA2dpService(); 1148 if ((a2dpService != null) && 1149 (BluetoothProfile.PRIORITY_AUTO_CONNECT != a2dpService.getPriority(device))){ 1150 adjustOtherSinkPriorities(a2dpService, device); 1151 a2dpService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT); 1152 } 1153 } 1154 } 1155 1156 boolean cancelBondProcess(BluetoothDevice device) { 1157 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1158 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1159 return cancelBondNative(addr); 1160 } 1161 1162 boolean removeBond(BluetoothDevice device) { 1163 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1164 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1165 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 1166 return false; 1167 } 1168 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 1169 msg.obj = device; 1170 mBondStateMachine.sendMessage(msg); 1171 return true; 1172 } 1173 1174 int getBondState(BluetoothDevice device) { 1175 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1176 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1177 if (deviceProp == null) { 1178 return BluetoothDevice.BOND_NONE; 1179 } 1180 return deviceProp.getBondState(); 1181 } 1182 1183 String getRemoteName(BluetoothDevice device) { 1184 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1185 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1186 if (deviceProp == null) return null; 1187 return deviceProp.getName(); 1188 } 1189 1190 String getRemoteAlias(BluetoothDevice device) { 1191 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1192 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1193 if (deviceProp == null) return null; 1194 return deviceProp.getAlias(); 1195 } 1196 1197 boolean setRemoteAlias(BluetoothDevice device, String name) { 1198 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1199 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1200 if (deviceProp == null) return false; 1201 deviceProp.setAlias(name); 1202 return true; 1203 } 1204 1205 int getRemoteClass(BluetoothDevice device) { 1206 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1207 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1208 if (deviceProp == null) return 0; 1209 1210 return deviceProp.getBluetoothClass(); 1211 } 1212 1213 ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 1214 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1215 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1216 if (deviceProp == null) return null; 1217 return deviceProp.getUuids(); 1218 } 1219 1220 boolean fetchRemoteUuids(BluetoothDevice device) { 1221 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1222 mRemoteDevices.fetchUuids(device); 1223 return true; 1224 } 1225 1226 boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 1227 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1228 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1229 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1230 return false; 1231 } 1232 1233 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1234 return pinReplyNative(addr, accept, len, pinCode); 1235 } 1236 1237 boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 1238 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1239 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1240 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1241 return false; 1242 } 1243 1244 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1245 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept, 1246 Utils.byteArrayToInt(passkey)); 1247 } 1248 1249 boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 1250 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1251 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1252 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1253 return false; 1254 } 1255 1256 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1257 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 1258 accept, 0); 1259 } 1260 1261 void sendConnectionStateChange(BluetoothDevice 1262 device, int profile, int state, int prevState) { 1263 // TODO(BT) permission check? 1264 // Since this is a binder call check if Bluetooth is on still 1265 if (getState() == BluetoothAdapter.STATE_OFF) return; 1266 1267 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 1268 1269 } 1270 1271 ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 1272 ParcelUuid uuid, int port, int flag) { 1273 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1274 int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()), 1275 type, Utils.uuidToByteArray(uuid), port, flag); 1276 if (fd < 0) { 1277 errorLog("Failed to connect socket"); 1278 return null; 1279 } 1280 return ParcelFileDescriptor.adoptFd(fd); 1281 } 1282 1283 ParcelFileDescriptor createSocketChannel(int type, String serviceName, 1284 ParcelUuid uuid, int port, int flag) { 1285 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1286 int fd = createSocketChannelNative(type, serviceName, 1287 Utils.uuidToByteArray(uuid), port, flag); 1288 if (fd < 0) { 1289 errorLog("Failed to create socket channel"); 1290 return null; 1291 } 1292 return ParcelFileDescriptor.adoptFd(fd); 1293 } 1294 1295 void registerCallback(IBluetoothCallback cb) { 1296 mCallbacks.register(cb); 1297 } 1298 1299 void unregisterCallback(IBluetoothCallback cb) { 1300 mCallbacks.unregister(cb); 1301 } 1302 1303 private static int convertScanModeToHal(int mode) { 1304 switch (mode) { 1305 case BluetoothAdapter.SCAN_MODE_NONE: 1306 return AbstractionLayer.BT_SCAN_MODE_NONE; 1307 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 1308 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 1309 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 1310 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1311 } 1312 // errorLog("Incorrect scan mode in convertScanModeToHal"); 1313 return -1; 1314 } 1315 1316 static int convertScanModeFromHal(int mode) { 1317 switch (mode) { 1318 case AbstractionLayer.BT_SCAN_MODE_NONE: 1319 return BluetoothAdapter.SCAN_MODE_NONE; 1320 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 1321 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 1322 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 1323 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1324 } 1325 //errorLog("Incorrect scan mode in convertScanModeFromHal"); 1326 return -1; 1327 } 1328 1329 private void debugLog(String msg) { 1330 Log.d(TAG +"(" +hashCode()+")", msg); 1331 } 1332 1333 private void errorLog(String msg) { 1334 Log.e(TAG +"(" +hashCode()+")", msg); 1335 } 1336 1337 private native static void classInitNative(); 1338 private native boolean initNative(); 1339 private native void cleanupNative(); 1340 /*package*/ native boolean enableNative(); 1341 /*package*/ native boolean disableNative(); 1342 /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val); 1343 /*package*/ native boolean getAdapterPropertiesNative(); 1344 /*package*/ native boolean getAdapterPropertyNative(int type); 1345 /*package*/ native boolean setAdapterPropertyNative(int type); 1346 /*package*/ native boolean 1347 setDevicePropertyNative(byte[] address, int type, byte[] val); 1348 /*package*/ native boolean getDevicePropertyNative(byte[] address, int type); 1349 1350 /*package*/ native boolean createBondNative(byte[] address); 1351 /*package*/ native boolean removeBondNative(byte[] address); 1352 /*package*/ native boolean cancelBondNative(byte[] address); 1353 1354 private native boolean startDiscoveryNative(); 1355 private native boolean cancelDiscoveryNative(); 1356 1357 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 1358 private native boolean sspReplyNative(byte[] address, int type, boolean 1359 accept, int passkey); 1360 1361 /*package*/ native boolean getRemoteServicesNative(byte[] address); 1362 1363 // TODO(BT) move this to ../btsock dir 1364 private native int connectSocketNative(byte[] address, int type, 1365 byte[] uuid, int port, int flag); 1366 private native int createSocketChannelNative(int type, String serviceName, 1367 byte[] uuid, int port, int flag); 1368 1369 protected void finalize() { 1370 cleanup(); 1371 if (TRACE_REF) { 1372 synchronized (AdapterService.class) { 1373 sRefCount--; 1374 Log.d(TAG, "REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount); 1375 } 1376 } 1377 } 1378} 1379