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