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