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