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