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