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