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