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