AdapterService.java revision 371e2047c485f8f75c2b63a38b36a65b72c2fa42
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.bluetooth.BluetoothActivityEnergyInfo; 36import android.content.BroadcastReceiver; 37import android.content.ContentResolver; 38import android.content.Context; 39import android.content.Intent; 40import android.content.IntentFilter; 41import android.content.SharedPreferences; 42import android.os.Binder; 43import android.os.Bundle; 44import android.os.Handler; 45import android.os.IBinder; 46import android.os.Message; 47import android.os.ParcelFileDescriptor; 48import android.os.ParcelUuid; 49import android.os.PowerManager; 50import android.os.Process; 51import android.os.RemoteCallbackList; 52import android.os.RemoteException; 53import android.os.SystemClock; 54import android.provider.Settings; 55import android.util.EventLog; 56import android.util.Log; 57import android.util.Pair; 58 59import com.android.bluetooth.a2dp.A2dpService; 60import com.android.bluetooth.hid.HidService; 61import com.android.bluetooth.hfp.HeadsetService; 62import com.android.bluetooth.hdp.HealthService; 63import com.android.bluetooth.pan.PanService; 64import com.android.bluetooth.sdp.SdpManager; 65import com.android.internal.R; 66import com.android.bluetooth.Utils; 67import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 68 69import java.io.FileDescriptor; 70import java.io.FileWriter; 71import java.io.IOException; 72import java.util.ArrayList; 73import java.util.HashMap; 74import java.util.Set; 75import java.util.Map; 76import java.util.Iterator; 77import java.util.Map.Entry; 78import java.util.List; 79 80import android.content.pm.PackageManager; 81import android.os.ServiceManager; 82 83public class AdapterService extends Service { 84 private static final String TAG = "BluetoothAdapterService"; 85 private static final boolean DBG = false; 86 private static final boolean TRACE_REF = false; 87 private static final int MIN_ADVT_INSTANCES_FOR_MA = 5; 88 private static final int MIN_OFFLOADED_FILTERS = 10; 89 private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024; 90 //For Debugging only 91 private static int sRefCount=0; 92 93 private int mStackReportedState; 94 private int mTxTimeTotalMs; 95 private int mRxTimeTotalMs; 96 private int mIdleTimeTotalMs; 97 private int mEnergyUsedTotalVoltAmpSecMicro; 98 99 private final ArrayList<ProfileService> mProfiles = new ArrayList<ProfileService>(); 100 101 public static final String ACTION_LOAD_ADAPTER_PROPERTIES = 102 "com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES"; 103 public static final String ACTION_SERVICE_STATE_CHANGED = 104 "com.android.bluetooth.btservice.action.STATE_CHANGED"; 105 public static final String EXTRA_ACTION="action"; 106 public static final int PROFILE_CONN_CONNECTED = 1; 107 public static final int PROFILE_CONN_REJECTED = 2; 108 109 private static final String ACTION_ALARM_WAKEUP = 110 "com.android.bluetooth.btservice.action.ALARM_WAKEUP"; 111 112 public static final String BLUETOOTH_ADMIN_PERM = 113 android.Manifest.permission.BLUETOOTH_ADMIN; 114 public static final String BLUETOOTH_PRIVILEGED = 115 android.Manifest.permission.BLUETOOTH_PRIVILEGED; 116 static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 117 static final String RECEIVE_MAP_PERM = android.Manifest.permission.RECEIVE_BLUETOOTH_MAP; 118 119 private static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = 120 "phonebook_access_permission"; 121 private static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE = 122 "message_access_permission"; 123 private static final String SIM_ACCESS_PERMISSION_PREFERENCE_FILE = 124 "sim_access_permission"; 125 126 private static final int ADAPTER_SERVICE_TYPE=Service.START_STICKY; 127 128 static { 129 classInitNative(); 130 } 131 132 private static AdapterService sAdapterService; 133 public static synchronized AdapterService getAdapterService(){ 134 if (sAdapterService != null && !sAdapterService.mCleaningUp) { 135 Log.d(TAG, "getAdapterService() - returning " + sAdapterService); 136 return sAdapterService; 137 } 138 if (DBG) { 139 if (sAdapterService == null) { 140 Log.d(TAG, "getAdapterService() - Service not available"); 141 } else if (sAdapterService.mCleaningUp) { 142 Log.d(TAG,"getAdapterService() - Service is cleaning up"); 143 } 144 } 145 return null; 146 } 147 148 private static synchronized void setAdapterService(AdapterService instance) { 149 if (instance != null && !instance.mCleaningUp) { 150 if (DBG) Log.d(TAG, "setAdapterService() - set to: " + sAdapterService); 151 sAdapterService = instance; 152 } else { 153 if (DBG) { 154 if (sAdapterService == null) { 155 Log.d(TAG, "setAdapterService() - Service not available"); 156 } else if (sAdapterService.mCleaningUp) { 157 Log.d(TAG,"setAdapterService() - Service is cleaning up"); 158 } 159 } 160 } 161 } 162 163 private static synchronized void clearAdapterService() { 164 sAdapterService = null; 165 } 166 167 private AdapterProperties mAdapterProperties; 168 private AdapterState mAdapterStateMachine; 169 private BondStateMachine mBondStateMachine; 170 private JniCallbacks mJniCallbacks; 171 private RemoteDevices mRemoteDevices; 172 173 /* TODO: Consider to remove the search API from this class, if changed to use call-back */ 174 private SdpManager mSdpManager = null; 175 176 private boolean mProfilesStarted; 177 private boolean mNativeAvailable; 178 private boolean mCleaningUp; 179 private HashMap<String,Integer> mProfileServicesState = new HashMap<String,Integer>(); 180 //Only BluetoothManagerService should be registered 181 private RemoteCallbackList<IBluetoothCallback> mCallbacks; 182 private int mCurrentRequestId; 183 private boolean mQuietmode = false; 184 185 private AlarmManager mAlarmManager; 186 private PendingIntent mPendingAlarm; 187 private PowerManager mPowerManager; 188 private PowerManager.WakeLock mWakeLock; 189 private String mWakeLockName; 190 191 public AdapterService() { 192 super(); 193 if (TRACE_REF) { 194 synchronized (AdapterService.class) { 195 sRefCount++; 196 debugLog("AdapterService() - REFCOUNT: CREATED. INSTANCE_COUNT" + sRefCount); 197 } 198 } 199 } 200 201 public void onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) { 202 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED); 203 m.obj = device; 204 m.arg1 = profileId; 205 m.arg2 = newState; 206 Bundle b = new Bundle(1); 207 b.putInt("prevState", prevState); 208 m.setData(b); 209 mHandler.sendMessage(m); 210 } 211 212 public void initProfilePriorities(BluetoothDevice device, ParcelUuid[] mUuids) { 213 if(mUuids == null) return; 214 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_INIT_PRIORITIES); 215 m.obj = device; 216 m.arg1 = mUuids.length; 217 Bundle b = new Bundle(1); 218 for(int i=0; i<mUuids.length; i++) { 219 b.putParcelable("uuids" + i, mUuids[i]); 220 } 221 m.setData(b); 222 mHandler.sendMessage(m); 223 } 224 225 private void processInitProfilePriorities (BluetoothDevice device, ParcelUuid[] uuids){ 226 HidService hidService = HidService.getHidService(); 227 A2dpService a2dpService = A2dpService.getA2dpService(); 228 HeadsetService headsetService = HeadsetService.getHeadsetService(); 229 230 // Set profile priorities only for the profiles discovered on the remote device. 231 // This avoids needless auto-connect attempts to profiles non-existent on the remote device 232 if ((hidService != null) && 233 (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hid) || 234 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp)) && 235 (hidService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){ 236 hidService.setPriority(device,BluetoothProfile.PRIORITY_ON); 237 } 238 239 // If we do not have a stored priority for A2DP then default to on. 240 if ((a2dpService != null) && 241 (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink) || 242 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AdvAudioDist)) && 243 (a2dpService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){ 244 a2dpService.setPriority(device,BluetoothProfile.PRIORITY_ON); 245 } 246 247 if ((headsetService != null) && 248 ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP) || 249 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) && 250 (headsetService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED))){ 251 headsetService.setPriority(device,BluetoothProfile.PRIORITY_ON); 252 } 253 } 254 255 private void processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) { 256 if (((profileId == BluetoothProfile.A2DP) ||(profileId == BluetoothProfile.HEADSET)) && 257 (newState == BluetoothProfile.STATE_CONNECTED)){ 258 debugLog( "Profile connected. Schedule missing profile connection if any"); 259 connectOtherProfile(device, PROFILE_CONN_CONNECTED); 260 setProfileAutoConnectionPriority(device, profileId); 261 } 262 IBluetooth.Stub binder = mBinder; 263 if (binder != null) { 264 try { 265 binder.sendConnectionStateChange(device, profileId, newState,prevState); 266 } catch (RemoteException re) { 267 errorLog("" + re); 268 } 269 } 270 } 271 272 public void addProfile(ProfileService profile) { 273 synchronized (mProfiles) { 274 mProfiles.add(profile); 275 } 276 } 277 278 public void removeProfile(ProfileService profile) { 279 synchronized (mProfiles) { 280 mProfiles.remove(profile); 281 } 282 } 283 284 public void onProfileServiceStateChanged(String serviceName, int state) { 285 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 286 m.obj=serviceName; 287 m.arg1 = state; 288 mHandler.sendMessage(m); 289 } 290 291 private void processProfileServiceStateChanged(String serviceName, int state) { 292 boolean doUpdate=false; 293 boolean isBleTurningOn; 294 boolean isBleTurningOff; 295 boolean isTurningOn; 296 boolean isTurningOff; 297 298 synchronized (mProfileServicesState) { 299 Integer prevState = mProfileServicesState.get(serviceName); 300 if (prevState != null && prevState != state) { 301 mProfileServicesState.put(serviceName,state); 302 doUpdate=true; 303 } 304 } 305 debugLog("onProfileServiceStateChange() serviceName=" + serviceName 306 + ", state=" + state +", doUpdate=" + doUpdate); 307 308 if (!doUpdate) { 309 return; 310 } 311 312 synchronized (mAdapterStateMachine) { 313 isTurningOff = mAdapterStateMachine.isTurningOff(); 314 isTurningOn = mAdapterStateMachine.isTurningOn(); 315 isBleTurningOn = mAdapterStateMachine.isBleTurningOn(); 316 isBleTurningOff = mAdapterStateMachine.isBleTurningOff(); 317 } 318 319 debugLog("processProfileServiceStateChanged() - serviceName=" + serviceName + 320 " isTurningOn=" + isTurningOn + " isTurningOff=" + isTurningOff + 321 " isBleTurningOn=" + isBleTurningOn + " isBleTurningOff=" + isBleTurningOff); 322 323 if (isBleTurningOn) { 324 if (serviceName.equals("com.android.bluetooth.gatt.GattService")) { 325 debugLog("GattService is started"); 326 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED)); 327 return; 328 } 329 330 } else if(isBleTurningOff) { 331 if (serviceName.equals("com.android.bluetooth.gatt.GattService")) { 332 debugLog("GattService stopped"); 333 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STOPPED)); 334 return; 335 } 336 337 } else if (isTurningOff) { 338 //On to BLE_ON 339 //Process stop or disable pending 340 //Check if all services are stopped if so, do cleanup 341 synchronized (mProfileServicesState) { 342 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator(); 343 while (i.hasNext()) { 344 Map.Entry<String,Integer> entry = i.next(); 345 debugLog("Service: " + entry.getKey()); 346 if (entry.getKey().equals("com.android.bluetooth.gatt.GattService")) { 347 debugLog("Skip GATT service - already started before"); 348 continue; 349 } 350 if (BluetoothAdapter.STATE_OFF != entry.getValue()) { 351 debugLog("onProfileServiceStateChange() - Profile still running: " 352 + entry.getKey()); 353 return; 354 } 355 } 356 } 357 debugLog("onProfileServiceStateChange() - All profile services stopped..."); 358 //Send message to state machine 359 mProfilesStarted=false; 360 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STOPPED)); 361 362 } else if (isTurningOn) { 363 //Process start pending 364 //Check if all services are started if so, update state 365 synchronized (mProfileServicesState) { 366 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator(); 367 while (i.hasNext()) { 368 Map.Entry<String,Integer> entry = i.next(); 369 debugLog("Service: " + entry.getKey()); 370 if (entry.getKey().equals("com.android.bluetooth.gatt.GattService")) { 371 debugLog("Skip GATT service - already started before"); 372 continue; 373 } 374 if (BluetoothAdapter.STATE_ON != entry.getValue()) { 375 debugLog("onProfileServiceStateChange() - Profile still not running:" 376 + entry.getKey()); 377 return; 378 } 379 } 380 } 381 debugLog("onProfileServiceStateChange() - All profile services started."); 382 mProfilesStarted=true; 383 //Send message to state machine 384 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED)); 385 } 386 } 387 388 @Override 389 public void onCreate() { 390 super.onCreate(); 391 debugLog("onCreate()"); 392 mBinder = new AdapterServiceBinder(this); 393 mAdapterProperties = new AdapterProperties(this); 394 mAdapterStateMachine = AdapterState.make(this, mAdapterProperties); 395 mJniCallbacks = new JniCallbacks(mAdapterStateMachine, mAdapterProperties); 396 initNative(); 397 mNativeAvailable=true; 398 mCallbacks = new RemoteCallbackList<IBluetoothCallback>(); 399 //Load the name and address 400 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR); 401 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME); 402 mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 403 mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 404 405 mSdpManager = SdpManager.init(this); 406 registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP)); 407 408 409 410 } 411 412 @Override 413 public IBinder onBind(Intent intent) { 414 debugLog("onBind()"); 415 return mBinder; 416 } 417 public boolean onUnbind(Intent intent) { 418 debugLog("onUnbind() - calling cleanup"); 419 cleanup(); 420 return super.onUnbind(intent); 421 } 422 423 public void onDestroy() { 424 debugLog("onDestroy()"); 425 } 426 427 void BleOnProcessStart() { 428 debugLog("BleOnProcessStart()"); 429 430 if (getApplicationContext().getResources().getBoolean( 431 R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) { 432 Config.init(getApplicationContext()); 433 } 434 435 Class[] supportedProfileServices = Config.getSupportedProfiles(); 436 //Initialize data objects 437 for (int i=0; i < supportedProfileServices.length;i++) { 438 mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF); 439 } 440 mRemoteDevices = new RemoteDevices(this); 441 mAdapterProperties.init(mRemoteDevices); 442 443 debugLog("BleOnProcessStart() - Make Bond State Machine"); 444 mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices); 445 446 mJniCallbacks.init(mBondStateMachine,mRemoteDevices); 447 448 //FIXME: Set static instance here??? 449 setAdapterService(this); 450 451 //Start Gatt service 452 setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON); 453 } 454 455 void startCoreServices() 456 { 457 debugLog("startCoreServices()"); 458 Class[] supportedProfileServices = Config.getSupportedProfiles(); 459 460 //Start profile services 461 if (!mProfilesStarted && supportedProfileServices.length >0) { 462 //Startup all profile services 463 setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON); 464 }else { 465 debugLog("startCoreProfiles(): Profile Services alreay started"); 466 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED)); 467 } 468 } 469 470 void startBluetoothDisable() { 471 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE)); 472 } 473 474 boolean stopProfileServices() { 475 Class[] supportedProfileServices = Config.getSupportedProfiles(); 476 if (mProfilesStarted && supportedProfileServices.length>0) { 477 setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF); 478 return true; 479 } 480 debugLog("stopProfileServices() - No profiles services to stop or already stopped."); 481 return false; 482 } 483 484 boolean stopGattProfileService() { 485 //TODO: can optimize this instead of looping around all supported profiles 486 debugLog("stopGattProfileService()"); 487 Class[] supportedProfileServices = Config.getSupportedProfiles(); 488 489 setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF); 490 return true; 491 } 492 493 494 void updateAdapterState(int prevState, int newState){ 495 if (mCallbacks !=null) { 496 int n=mCallbacks.beginBroadcast(); 497 debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers."); 498 for (int i=0; i <n;i++) { 499 try { 500 mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState); 501 } catch (RemoteException e) { 502 debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")"); 503 } 504 } 505 mCallbacks.finishBroadcast(); 506 } 507 } 508 509 void cleanup () { 510 debugLog("cleanup()"); 511 if (mCleaningUp) { 512 errorLog("cleanup() - Service already starting to cleanup, ignoring request..."); 513 return; 514 } 515 516 mCleaningUp = true; 517 518 unregisterReceiver(mAlarmBroadcastReceiver); 519 520 if (mPendingAlarm != null) { 521 mAlarmManager.cancel(mPendingAlarm); 522 mPendingAlarm = null; 523 } 524 525 // This wake lock release may also be called concurrently by 526 // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here. 527 synchronized (this) { 528 if (mWakeLock != null) { 529 mWakeLock.release(); 530 mWakeLock = null; 531 } 532 } 533 534 if (mAdapterStateMachine != null) { 535 mAdapterStateMachine.doQuit(); 536 mAdapterStateMachine.cleanup(); 537 } 538 539 if (mBondStateMachine != null) { 540 mBondStateMachine.doQuit(); 541 mBondStateMachine.cleanup(); 542 } 543 544 if (mRemoteDevices != null) { 545 mRemoteDevices.cleanup(); 546 } 547 548 if(mSdpManager != null) { 549 mSdpManager.cleanup(); 550 mSdpManager = null; 551 } 552 553 if (mNativeAvailable) { 554 debugLog("cleanup() - Cleaning up adapter native"); 555 cleanupNative(); 556 mNativeAvailable=false; 557 } 558 559 if (mAdapterProperties != null) { 560 mAdapterProperties.cleanup(); 561 } 562 563 if (mJniCallbacks != null) { 564 mJniCallbacks.cleanup(); 565 } 566 567 if (mProfileServicesState != null) { 568 mProfileServicesState.clear(); 569 } 570 571 clearAdapterService(); 572 573 if (mBinder != null) { 574 mBinder.cleanup(); 575 mBinder = null; //Do not remove. Otherwise Binder leak! 576 } 577 578 if (mCallbacks !=null) { 579 mCallbacks.kill(); 580 } 581 582 System.exit(0); 583 } 584 585 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1; 586 private static final int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED=20; 587 private static final int MESSAGE_CONNECT_OTHER_PROFILES = 30; 588 private static final int MESSAGE_PROFILE_INIT_PRIORITIES=40; 589 private static final int CONNECT_OTHER_PROFILES_TIMEOUT= 6000; 590 591 private final Handler mHandler = new Handler() { 592 @Override 593 public void handleMessage(Message msg) { 594 debugLog("handleMessage() - Message: " + msg.what); 595 596 switch (msg.what) { 597 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: { 598 debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 599 processProfileServiceStateChanged((String) msg.obj, msg.arg1); 600 } 601 break; 602 case MESSAGE_PROFILE_CONNECTION_STATE_CHANGED: { 603 debugLog( "handleMessage() - MESSAGE_PROFILE_CONNECTION_STATE_CHANGED"); 604 processProfileStateChanged((BluetoothDevice) msg.obj, msg.arg1,msg.arg2, msg.getData().getInt("prevState",BluetoothAdapter.ERROR)); 605 } 606 break; 607 case MESSAGE_PROFILE_INIT_PRIORITIES: { 608 debugLog( "handleMessage() - MESSAGE_PROFILE_INIT_PRIORITIES"); 609 ParcelUuid[] mUuids = new ParcelUuid[msg.arg1]; 610 for(int i=0; i<mUuids.length; i++) { 611 mUuids[i] = msg.getData().getParcelable("uuids" + i); 612 } 613 processInitProfilePriorities((BluetoothDevice) msg.obj, 614 mUuids); 615 } 616 break; 617 case MESSAGE_CONNECT_OTHER_PROFILES: { 618 debugLog( "handleMessage() - MESSAGE_CONNECT_OTHER_PROFILES"); 619 processConnectOtherProfiles((BluetoothDevice) msg.obj,msg.arg1); 620 } 621 break; 622 } 623 } 624 }; 625 626 @SuppressWarnings("rawtypes") 627 private void setGattProfileServiceState(Class[] services, int state) { 628 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 629 Log.w(TAG,"setGattProfileServiceState(): invalid state...Leaving..."); 630 return; 631 } 632 633 int expectedCurrentState= BluetoothAdapter.STATE_OFF; 634 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 635 636 if (state == BluetoothAdapter.STATE_OFF) { 637 expectedCurrentState= BluetoothAdapter.STATE_ON; 638 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 639 } 640 641 for (int i=0; i <services.length;i++) { 642 String serviceName = services[i].getName(); 643 String simpleName = services[i].getSimpleName(); 644 645 if (simpleName.equals("GattService")) { 646 Integer serviceState = mProfileServicesState.get(serviceName); 647 648 if(serviceState != null && serviceState != expectedCurrentState) { 649 debugLog("setProfileServiceState() - Unable to " 650 + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" ) 651 + " service " + serviceName 652 + ". Invalid state: " + serviceState); 653 continue; 654 } 655 debugLog("setProfileServiceState() - " 656 + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting") 657 + " service " + serviceName); 658 659 mProfileServicesState.put(serviceName,pendingState); 660 Intent intent = new Intent(this,services[i]); 661 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); 662 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); 663 startService(intent); 664 return; 665 } 666 } 667 } 668 669 670 @SuppressWarnings("rawtypes") 671 private void setProfileServiceState(Class[] services, int state) { 672 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 673 debugLog("setProfileServiceState() - Invalid state, leaving..."); 674 return; 675 } 676 677 int expectedCurrentState= BluetoothAdapter.STATE_OFF; 678 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 679 if (state == BluetoothAdapter.STATE_OFF) { 680 expectedCurrentState= BluetoothAdapter.STATE_ON; 681 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 682 } 683 684 for (int i=0; i <services.length;i++) { 685 String serviceName = services[i].getName(); 686 String simpleName = services[i].getSimpleName(); 687 688 if (simpleName.equals("GattService")) continue; 689 690 Integer serviceState = mProfileServicesState.get(serviceName); 691 if(serviceState != null && serviceState != expectedCurrentState) { 692 debugLog("setProfileServiceState() - Unable to " 693 + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" ) 694 + " service " + serviceName 695 + ". Invalid state: " + serviceState); 696 continue; 697 } 698 699 debugLog("setProfileServiceState() - " 700 + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting") 701 + " service " + serviceName); 702 703 mProfileServicesState.put(serviceName,pendingState); 704 Intent intent = new Intent(this,services[i]); 705 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); 706 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); 707 startService(intent); 708 } 709 } 710 711 private boolean isAvailable() { 712 return !mCleaningUp; 713 } 714 715 /** 716 * Handlers for incoming service calls 717 */ 718 private AdapterServiceBinder mBinder; 719 720 /** 721 * The Binder implementation must be declared to be a static class, with 722 * the AdapterService instance passed in the constructor. Furthermore, 723 * when the AdapterService shuts down, the reference to the AdapterService 724 * must be explicitly removed. 725 * 726 * Otherwise, a memory leak can occur from repeated starting/stopping the 727 * service...Please refer to android.os.Binder for further details on 728 * why an inner instance class should be avoided. 729 * 730 */ 731 private static class AdapterServiceBinder extends IBluetooth.Stub { 732 private AdapterService mService; 733 734 public AdapterServiceBinder(AdapterService svc) { 735 mService = svc; 736 } 737 public boolean cleanup() { 738 mService = null; 739 return true; 740 } 741 742 public AdapterService getService() { 743 if (mService != null && mService.isAvailable()) { 744 return mService; 745 } 746 return null; 747 } 748 public boolean isEnabled() { 749 // don't check caller, may be called from system UI 750 AdapterService service = getService(); 751 if (service == null) return false; 752 return service.isEnabled(); 753 } 754 755 public int getState() { 756 // don't check caller, may be called from system UI 757 AdapterService service = getService(); 758 if (service == null) return BluetoothAdapter.STATE_OFF; 759 return service.getState(); 760 } 761 762 public boolean enable() { 763 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 764 (!Utils.checkCaller())) { 765 Log.w(TAG, "enable() - Not allowed for non-active user and non system user"); 766 return false; 767 } 768 AdapterService service = getService(); 769 if (service == null) return false; 770 return service.enable(); 771 } 772 773 public boolean enableNoAutoConnect() { 774 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 775 (!Utils.checkCaller())) { 776 Log.w(TAG, "enableNoAuto() - Not allowed for non-active user and non system user"); 777 return false; 778 } 779 780 AdapterService service = getService(); 781 if (service == null) return false; 782 return service.enableNoAutoConnect(); 783 } 784 785 public boolean disable() { 786 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 787 (!Utils.checkCaller())) { 788 Log.w(TAG, "disable() - Not allowed for non-active user and non system user"); 789 return false; 790 } 791 792 AdapterService service = getService(); 793 if (service == null) return false; 794 return service.disable(); 795 } 796 797 public String getAddress() { 798 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 799 (!Utils.checkCallerAllowManagedProfiles(mService))) { 800 Log.w(TAG, "getAddress() - Not allowed for non-active user and non system user"); 801 return null; 802 } 803 804 AdapterService service = getService(); 805 if (service == null) return null; 806 return service.getAddress(); 807 } 808 809 public ParcelUuid[] getUuids() { 810 if (!Utils.checkCaller()) { 811 Log.w(TAG, "getUuids() - Not allowed for non-active user"); 812 return new ParcelUuid[0]; 813 } 814 815 AdapterService service = getService(); 816 if (service == null) return new ParcelUuid[0]; 817 return service.getUuids(); 818 } 819 820 public String getName() { 821 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 822 (!Utils.checkCaller())) { 823 Log.w(TAG, "getName() - Not allowed for non-active user and non system user"); 824 return null; 825 } 826 827 AdapterService service = getService(); 828 if (service == null) return null; 829 return service.getName(); 830 } 831 832 public boolean setName(String name) { 833 if (!Utils.checkCaller()) { 834 Log.w(TAG, "setName() - Not allowed for non-active user"); 835 return false; 836 } 837 838 AdapterService service = getService(); 839 if (service == null) return false; 840 return service.setName(name); 841 } 842 843 public int getScanMode() { 844 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 845 Log.w(TAG, "getScanMode() - Not allowed for non-active user"); 846 return BluetoothAdapter.SCAN_MODE_NONE; 847 } 848 849 AdapterService service = getService(); 850 if (service == null) return BluetoothAdapter.SCAN_MODE_NONE; 851 return service.getScanMode(); 852 } 853 854 public boolean setScanMode(int mode, int duration) { 855 if (!Utils.checkCaller()) { 856 Log.w(TAG, "setScanMode() - Not allowed for non-active user"); 857 return false; 858 } 859 860 AdapterService service = getService(); 861 if (service == null) return false; 862 return service.setScanMode(mode,duration); 863 } 864 865 public int getDiscoverableTimeout() { 866 if (!Utils.checkCaller()) { 867 Log.w(TAG, "getDiscoverableTimeout() - Not allowed for non-active user"); 868 return 0; 869 } 870 871 AdapterService service = getService(); 872 if (service == null) return 0; 873 return service.getDiscoverableTimeout(); 874 } 875 876 public boolean setDiscoverableTimeout(int timeout) { 877 if (!Utils.checkCaller()) { 878 Log.w(TAG, "setDiscoverableTimeout() - Not allowed for non-active user"); 879 return false; 880 } 881 882 AdapterService service = getService(); 883 if (service == null) return false; 884 return service.setDiscoverableTimeout(timeout); 885 } 886 887 public boolean startDiscovery() { 888 if (!Utils.checkCaller()) { 889 Log.w(TAG, "startDiscovery() - Not allowed for non-active user"); 890 return false; 891 } 892 893 AdapterService service = getService(); 894 if (service == null) return false; 895 return service.startDiscovery(); 896 } 897 898 public boolean cancelDiscovery() { 899 if (!Utils.checkCaller()) { 900 Log.w(TAG, "cancelDiscovery() - Not allowed for non-active user"); 901 return false; 902 } 903 904 AdapterService service = getService(); 905 if (service == null) return false; 906 return service.cancelDiscovery(); 907 } 908 public boolean isDiscovering() { 909 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 910 Log.w(TAG, "isDiscovering() - Not allowed for non-active user"); 911 return false; 912 } 913 914 AdapterService service = getService(); 915 if (service == null) return false; 916 return service.isDiscovering(); 917 } 918 919 public BluetoothDevice[] getBondedDevices() { 920 // don't check caller, may be called from system UI 921 AdapterService service = getService(); 922 if (service == null) return new BluetoothDevice[0]; 923 return service.getBondedDevices(); 924 } 925 926 public int getAdapterConnectionState() { 927 // don't check caller, may be called from system UI 928 AdapterService service = getService(); 929 if (service == null) return BluetoothAdapter.STATE_DISCONNECTED; 930 return service.getAdapterConnectionState(); 931 } 932 933 public int getProfileConnectionState(int profile) { 934 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 935 Log.w(TAG, "getProfileConnectionState- Not allowed for non-active user"); 936 return BluetoothProfile.STATE_DISCONNECTED; 937 } 938 939 AdapterService service = getService(); 940 if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 941 return service.getProfileConnectionState(profile); 942 } 943 944 public boolean createBond(BluetoothDevice device, int transport) { 945 if (!Utils.checkCaller()) { 946 Log.w(TAG, "createBond() - Not allowed for non-active user"); 947 return false; 948 } 949 950 AdapterService service = getService(); 951 if (service == null) return false; 952 return service.createBond(device, transport); 953 } 954 955 public boolean cancelBondProcess(BluetoothDevice device) { 956 if (!Utils.checkCaller()) { 957 Log.w(TAG, "cancelBondProcess() - Not allowed for non-active user"); 958 return false; 959 } 960 961 AdapterService service = getService(); 962 if (service == null) return false; 963 return service.cancelBondProcess(device); 964 } 965 966 public boolean removeBond(BluetoothDevice device) { 967 if (!Utils.checkCaller()) { 968 Log.w(TAG, "removeBond() - Not allowed for non-active user"); 969 return false; 970 } 971 972 AdapterService service = getService(); 973 if (service == null) return false; 974 return service.removeBond(device); 975 } 976 977 public int getBondState(BluetoothDevice device) { 978 // don't check caller, may be called from system UI 979 AdapterService service = getService(); 980 if (service == null) return BluetoothDevice.BOND_NONE; 981 return service.getBondState(device); 982 } 983 984 public int getConnectionState(BluetoothDevice device) { 985 AdapterService service = getService(); 986 if (service == null) return 0; 987 return service.getConnectionState(device); 988 } 989 990 public String getRemoteName(BluetoothDevice device) { 991 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 992 Log.w(TAG, "getRemoteName() - Not allowed for non-active user"); 993 return null; 994 } 995 996 AdapterService service = getService(); 997 if (service == null) return null; 998 return service.getRemoteName(device); 999 } 1000 1001 public int getRemoteType(BluetoothDevice device) { 1002 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1003 Log.w(TAG, "getRemoteType() - Not allowed for non-active user"); 1004 return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1005 } 1006 1007 AdapterService service = getService(); 1008 if (service == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1009 return service.getRemoteType(device); 1010 } 1011 1012 public String getRemoteAlias(BluetoothDevice device) { 1013 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1014 Log.w(TAG, "getRemoteAlias() - Not allowed for non-active user"); 1015 return null; 1016 } 1017 1018 AdapterService service = getService(); 1019 if (service == null) return null; 1020 return service.getRemoteAlias(device); 1021 } 1022 1023 public boolean setRemoteAlias(BluetoothDevice device, String name) { 1024 if (!Utils.checkCaller()) { 1025 Log.w(TAG, "setRemoteAlias() - Not allowed for non-active user"); 1026 return false; 1027 } 1028 1029 AdapterService service = getService(); 1030 if (service == null) return false; 1031 return service.setRemoteAlias(device, name); 1032 } 1033 1034 public int getRemoteClass(BluetoothDevice device) { 1035 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1036 Log.w(TAG, "getRemoteClass() - Not allowed for non-active user"); 1037 return 0; 1038 } 1039 1040 AdapterService service = getService(); 1041 if (service == null) return 0; 1042 return service.getRemoteClass(device); 1043 } 1044 1045 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 1046 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1047 Log.w(TAG, "getRemoteUuids() - Not allowed for non-active user"); 1048 return new ParcelUuid[0]; 1049 } 1050 1051 AdapterService service = getService(); 1052 if (service == null) return new ParcelUuid[0]; 1053 return service.getRemoteUuids(device); 1054 } 1055 1056 public boolean fetchRemoteUuids(BluetoothDevice device) { 1057 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1058 Log.w(TAG, "fetchRemoteUuids() - Not allowed for non-active user"); 1059 return false; 1060 } 1061 1062 AdapterService service = getService(); 1063 if (service == null) return false; 1064 return service.fetchRemoteUuids(device); 1065 } 1066 1067 1068 1069 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 1070 if (!Utils.checkCaller()) { 1071 Log.w(TAG, "setPin() - Not allowed for non-active user"); 1072 return false; 1073 } 1074 1075 AdapterService service = getService(); 1076 if (service == null) return false; 1077 return service.setPin(device, accept, len, pinCode); 1078 } 1079 1080 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 1081 if (!Utils.checkCaller()) { 1082 Log.w(TAG, "setPasskey() - Not allowed for non-active user"); 1083 return false; 1084 } 1085 1086 AdapterService service = getService(); 1087 if (service == null) return false; 1088 return service.setPasskey(device, accept, len, passkey); 1089 } 1090 1091 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 1092 if (!Utils.checkCaller()) { 1093 Log.w(TAG, "setPairingConfirmation() - Not allowed for non-active user"); 1094 return false; 1095 } 1096 1097 AdapterService service = getService(); 1098 if (service == null) return false; 1099 return service.setPairingConfirmation(device, accept); 1100 } 1101 1102 public int getPhonebookAccessPermission(BluetoothDevice device) { 1103 if (!Utils.checkCaller()) { 1104 Log.w(TAG, "getPhonebookAccessPermission() - Not allowed for non-active user"); 1105 return BluetoothDevice.ACCESS_UNKNOWN; 1106 } 1107 1108 AdapterService service = getService(); 1109 if (service == null) return BluetoothDevice.ACCESS_UNKNOWN; 1110 return service.getPhonebookAccessPermission(device); 1111 } 1112 1113 public boolean setPhonebookAccessPermission(BluetoothDevice device, int value) { 1114 if (!Utils.checkCaller()) { 1115 Log.w(TAG, "setPhonebookAccessPermission() - Not allowed for non-active user"); 1116 return false; 1117 } 1118 1119 AdapterService service = getService(); 1120 if (service == null) return false; 1121 return service.setPhonebookAccessPermission(device, value); 1122 } 1123 1124 public int getMessageAccessPermission(BluetoothDevice device) { 1125 if (!Utils.checkCaller()) { 1126 Log.w(TAG, "getMessageAccessPermission() - Not allowed for non-active user"); 1127 return BluetoothDevice.ACCESS_UNKNOWN; 1128 } 1129 1130 AdapterService service = getService(); 1131 if (service == null) return BluetoothDevice.ACCESS_UNKNOWN; 1132 return service.getMessageAccessPermission(device); 1133 } 1134 1135 public boolean setMessageAccessPermission(BluetoothDevice device, int value) { 1136 if (!Utils.checkCaller()) { 1137 Log.w(TAG, "setMessageAccessPermission() - Not allowed for non-active user"); 1138 return false; 1139 } 1140 1141 AdapterService service = getService(); 1142 if (service == null) return false; 1143 return service.setMessageAccessPermission(device, value); 1144 } 1145 1146 public int getSimAccessPermission(BluetoothDevice device) { 1147 if (!Utils.checkCaller()) { 1148 Log.w(TAG, "getSimAccessPermission() - Not allowed for non-active user"); 1149 return BluetoothDevice.ACCESS_UNKNOWN; 1150 } 1151 1152 AdapterService service = getService(); 1153 if (service == null) return BluetoothDevice.ACCESS_UNKNOWN; 1154 return service.getSimAccessPermission(device); 1155 } 1156 1157 public boolean setSimAccessPermission(BluetoothDevice device, int value) { 1158 if (!Utils.checkCaller()) { 1159 Log.w(TAG, "setSimAccessPermission() - Not allowed for non-active user"); 1160 return false; 1161 } 1162 1163 AdapterService service = getService(); 1164 if (service == null) return false; 1165 return service.setSimAccessPermission(device, value); 1166 } 1167 1168 public void sendConnectionStateChange(BluetoothDevice 1169 device, int profile, int state, int prevState) { 1170 AdapterService service = getService(); 1171 if (service == null) return; 1172 service.sendConnectionStateChange(device, profile, state, prevState); 1173 } 1174 1175 public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 1176 ParcelUuid uuid, int port, int flag) { 1177 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1178 Log.w(TAG, "connectSocket() - Not allowed for non-active user"); 1179 return null; 1180 } 1181 1182 AdapterService service = getService(); 1183 if (service == null) return null; 1184 return service.connectSocket(device, type, uuid, port, flag); 1185 } 1186 1187 public ParcelFileDescriptor createSocketChannel(int type, String serviceName, 1188 ParcelUuid uuid, int port, int flag) { 1189 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1190 Log.w(TAG, "createSocketChannel() - Not allowed for non-active user"); 1191 return null; 1192 } 1193 1194 AdapterService service = getService(); 1195 if (service == null) return null; 1196 return service.createSocketChannel(type, serviceName, uuid, port, flag); 1197 } 1198 public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) { 1199 if (!Utils.checkCaller()) { 1200 Log.w(TAG,"sdpSea(): not allowed for non-active user"); 1201 return false; 1202 } 1203 1204 AdapterService service = getService(); 1205 if (service == null) return false; 1206 return service.sdpSearch(device,uuid); 1207 } 1208 1209 public boolean configHciSnoopLog(boolean enable) { 1210 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 1211 EventLog.writeEvent(0x534e4554 /* SNET */, "Bluetooth", Binder.getCallingUid(), 1212 "configHciSnoopLog() - Not allowed for non-active user b/18643224"); 1213 return false; 1214 } 1215 1216 AdapterService service = getService(); 1217 if (service == null) return false; 1218 return service.configHciSnoopLog(enable); 1219 } 1220 1221 public boolean factoryReset() { 1222 AdapterService service = getService(); 1223 if (service == null) return false; 1224 service.disable(); 1225 return service.factoryReset(); 1226 1227 } 1228 1229 public void registerCallback(IBluetoothCallback cb) { 1230 AdapterService service = getService(); 1231 if (service == null) return ; 1232 service.registerCallback(cb); 1233 } 1234 1235 public void unregisterCallback(IBluetoothCallback cb) { 1236 AdapterService service = getService(); 1237 if (service == null) return ; 1238 service.unregisterCallback(cb); 1239 } 1240 1241 public boolean isMultiAdvertisementSupported() { 1242 AdapterService service = getService(); 1243 if (service == null) return false; 1244 return service.isMultiAdvertisementSupported(); 1245 } 1246 1247 public boolean isPeripheralModeSupported() { 1248 AdapterService service = getService(); 1249 if (service == null) return false; 1250 return service.isPeripheralModeSupported(); 1251 } 1252 1253 public boolean isOffloadedFilteringSupported() { 1254 AdapterService service = getService(); 1255 if (service == null) return false; 1256 int val = service.getNumOfOffloadedScanFilterSupported(); 1257 return (val >= MIN_OFFLOADED_FILTERS); 1258 } 1259 1260 public boolean isOffloadedScanBatchingSupported() { 1261 AdapterService service = getService(); 1262 if (service == null) return false; 1263 int val = service.getOffloadedScanResultStorage(); 1264 return (val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES); 1265 } 1266 1267 public boolean isActivityAndEnergyReportingSupported() { 1268 AdapterService service = getService(); 1269 if (service == null) return false; 1270 return service.isActivityAndEnergyReportingSupported(); 1271 } 1272 1273 public void getActivityEnergyInfoFromController() { 1274 AdapterService service = getService(); 1275 if (service == null) return; 1276 service.getActivityEnergyInfoFromController(); 1277 } 1278 1279 public BluetoothActivityEnergyInfo reportActivityInfo() { 1280 AdapterService service = getService(); 1281 if (service == null) return null; 1282 return service.reportActivityInfo(); 1283 } 1284 1285 public void dump(ParcelFileDescriptor fd) { 1286 AdapterService service = getService(); 1287 if (service == null) return; 1288 service.dump(fd.getFileDescriptor()); 1289 } 1290 1291 public void onLeServiceUp(){ 1292 AdapterService service = getService(); 1293 if (service == null) return; 1294 service.onLeServiceUp(); 1295 } 1296 1297 public void onBrEdrDown(){ 1298 AdapterService service = getService(); 1299 if (service == null) return; 1300 service.onBrEdrDown(); 1301 } 1302 }; 1303 1304 // ----API Methods-------- 1305 1306 boolean isEnabled() { 1307 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1308 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 1309 } 1310 1311 int getState() { 1312 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1313 if (mAdapterProperties != null) return mAdapterProperties.getState(); 1314 return BluetoothAdapter.STATE_OFF; 1315 } 1316 1317 boolean enable() { 1318 return enable (false); 1319 } 1320 1321 public boolean enableNoAutoConnect() { 1322 return enable (true); 1323 } 1324 1325 public synchronized boolean enable(boolean quietMode) { 1326 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1327 1328 debugLog("enable() - Enable called with quiet mode status = " + mQuietmode); 1329 mQuietmode = quietMode; 1330 Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON); 1331 mAdapterStateMachine.sendMessage(m); 1332 return true; 1333 } 1334 1335 boolean disable() { 1336 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1337 1338 debugLog("disable() called..."); 1339 Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_OFF); 1340 mAdapterStateMachine.sendMessage(m); 1341 return true; 1342 } 1343 1344 String getAddress() { 1345 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1346 1347 String addrString = null; 1348 byte[] address = mAdapterProperties.getAddress(); 1349 return Utils.getAddressStringFromByte(address); 1350 } 1351 1352 ParcelUuid[] getUuids() { 1353 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1354 1355 return mAdapterProperties.getUuids(); 1356 } 1357 1358 String getName() { 1359 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1360 "Need BLUETOOTH permission"); 1361 1362 try { 1363 return mAdapterProperties.getName(); 1364 } catch (Throwable t) { 1365 debugLog("getName() - Unexpected exception (" + t + ")"); 1366 } 1367 return null; 1368 } 1369 1370 boolean setName(String name) { 1371 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1372 "Need BLUETOOTH ADMIN permission"); 1373 1374 return mAdapterProperties.setName(name); 1375 } 1376 1377 int getScanMode() { 1378 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1379 1380 return mAdapterProperties.getScanMode(); 1381 } 1382 1383 boolean setScanMode(int mode, int duration) { 1384 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1385 1386 setDiscoverableTimeout(duration); 1387 1388 int newMode = convertScanModeToHal(mode); 1389 return mAdapterProperties.setScanMode(newMode); 1390 } 1391 1392 int getDiscoverableTimeout() { 1393 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1394 1395 return mAdapterProperties.getDiscoverableTimeout(); 1396 } 1397 1398 boolean setDiscoverableTimeout(int timeout) { 1399 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1400 1401 return mAdapterProperties.setDiscoverableTimeout(timeout); 1402 } 1403 1404 boolean startDiscovery() { 1405 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1406 "Need BLUETOOTH ADMIN permission"); 1407 1408 return startDiscoveryNative(); 1409 } 1410 1411 boolean cancelDiscovery() { 1412 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1413 "Need BLUETOOTH ADMIN permission"); 1414 1415 return cancelDiscoveryNative(); 1416 } 1417 1418 boolean isDiscovering() { 1419 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1420 1421 return mAdapterProperties.isDiscovering(); 1422 } 1423 1424 BluetoothDevice[] getBondedDevices() { 1425 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1426 return mAdapterProperties.getBondedDevices(); 1427 } 1428 1429 int getAdapterConnectionState() { 1430 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1431 return mAdapterProperties.getConnectionState(); 1432 } 1433 1434 int getProfileConnectionState(int profile) { 1435 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1436 1437 return mAdapterProperties.getProfileConnectionState(profile); 1438 } 1439 boolean sdpSearch(BluetoothDevice device,ParcelUuid uuid) { 1440 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1441 if(mSdpManager != null) { 1442 mSdpManager.sdpSearch(device,uuid); 1443 return true; 1444 } else { 1445 return false; 1446 } 1447 } 1448 1449 1450 boolean createBond(BluetoothDevice device, int transport) { 1451 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1452 "Need BLUETOOTH ADMIN permission"); 1453 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1454 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 1455 return false; 1456 } 1457 1458 // Pairing is unreliable while scanning, so cancel discovery 1459 // Note, remove this when native stack improves 1460 cancelDiscoveryNative(); 1461 1462 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 1463 msg.obj = device; 1464 msg.arg1 = transport; 1465 mBondStateMachine.sendMessage(msg); 1466 return true; 1467 } 1468 1469 public boolean isQuietModeEnabled() { 1470 debugLog("isQuetModeEnabled() - Enabled = " + mQuietmode); 1471 return mQuietmode; 1472 } 1473 1474 public void autoConnect(){ 1475 if (getState() != BluetoothAdapter.STATE_ON){ 1476 errorLog("autoConnect() - BT is not ON. Exiting autoConnect"); 1477 return; 1478 } 1479 if (isQuietModeEnabled() == false) { 1480 debugLog( "autoConnect() - Initiate auto connection on BT on..."); 1481 autoConnectHeadset(); 1482 autoConnectA2dp(); 1483 } 1484 else { 1485 debugLog( "autoConnect() - BT is in quiet mode. Not initiating auto connections"); 1486 } 1487 } 1488 1489 private void autoConnectHeadset(){ 1490 HeadsetService hsService = HeadsetService.getHeadsetService(); 1491 1492 BluetoothDevice bondedDevices[] = getBondedDevices(); 1493 if ((bondedDevices == null) ||(hsService == null)) { 1494 return; 1495 } 1496 for (BluetoothDevice device : bondedDevices) { 1497 if (hsService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){ 1498 debugLog("autoConnectHeadset() - Connecting HFP with " + device.toString()); 1499 hsService.connect(device); 1500 } 1501 } 1502 } 1503 1504 private void autoConnectA2dp(){ 1505 A2dpService a2dpSservice = A2dpService.getA2dpService(); 1506 BluetoothDevice bondedDevices[] = getBondedDevices(); 1507 if ((bondedDevices == null) ||(a2dpSservice == null)) { 1508 return; 1509 } 1510 for (BluetoothDevice device : bondedDevices) { 1511 if (a2dpSservice.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){ 1512 debugLog("autoConnectA2dp() - Connecting A2DP with " + device.toString()); 1513 a2dpSservice.connect(device); 1514 } 1515 } 1516 } 1517 1518 public void connectOtherProfile(BluetoothDevice device, int firstProfileStatus){ 1519 if ((mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES) == false) && 1520 (isQuietModeEnabled()== false)){ 1521 Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES); 1522 m.obj = device; 1523 m.arg1 = (int)firstProfileStatus; 1524 mHandler.sendMessageDelayed(m,CONNECT_OTHER_PROFILES_TIMEOUT); 1525 } 1526 } 1527 1528 private void processConnectOtherProfiles (BluetoothDevice device, int firstProfileStatus){ 1529 if (getState()!= BluetoothAdapter.STATE_ON){ 1530 return; 1531 } 1532 HeadsetService hsService = HeadsetService.getHeadsetService(); 1533 A2dpService a2dpService = A2dpService.getA2dpService(); 1534 1535 // if any of the profile service is null, second profile connection not required 1536 if ((hsService == null) ||(a2dpService == null )){ 1537 return; 1538 } 1539 List<BluetoothDevice> a2dpConnDevList= a2dpService.getConnectedDevices(); 1540 List<BluetoothDevice> hfConnDevList= hsService.getConnectedDevices(); 1541 // Check if the device is in disconnected state and if so return 1542 // We ned to connect other profile only if one of the profile is still in connected state 1543 // This is required to avoide a race condition in which profiles would 1544 // automaticlly connect if the disconnection is initiated within 6 seconds of connection 1545 //First profile connection being rejected is an exception 1546 if((hfConnDevList.isEmpty() && a2dpConnDevList.isEmpty())&& 1547 (PROFILE_CONN_CONNECTED == firstProfileStatus)){ 1548 return; 1549 } 1550 if((hfConnDevList.isEmpty()) && 1551 (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){ 1552 hsService.connect(device); 1553 } 1554 else if((a2dpConnDevList.isEmpty()) && 1555 (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){ 1556 a2dpService.connect(device); 1557 } 1558 } 1559 1560 private void adjustOtherHeadsetPriorities(HeadsetService hsService, 1561 List<BluetoothDevice> connectedDeviceList) { 1562 for (BluetoothDevice device : getBondedDevices()) { 1563 if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && 1564 !connectedDeviceList.contains(device)) { 1565 hsService.setPriority(device, BluetoothProfile.PRIORITY_ON); 1566 } 1567 } 1568 } 1569 1570 private void adjustOtherSinkPriorities(A2dpService a2dpService, 1571 BluetoothDevice connectedDevice) { 1572 for (BluetoothDevice device : getBondedDevices()) { 1573 if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && 1574 !device.equals(connectedDevice)) { 1575 a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON); 1576 } 1577 } 1578 } 1579 1580 void setProfileAutoConnectionPriority (BluetoothDevice device, int profileId){ 1581 if (profileId == BluetoothProfile.HEADSET) { 1582 HeadsetService hsService = HeadsetService.getHeadsetService(); 1583 List<BluetoothDevice> deviceList = hsService.getConnectedDevices(); 1584 if ((hsService != null) && 1585 (BluetoothProfile.PRIORITY_AUTO_CONNECT != hsService.getPriority(device))){ 1586 adjustOtherHeadsetPriorities(hsService, deviceList); 1587 hsService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT); 1588 } 1589 } 1590 else if (profileId == BluetoothProfile.A2DP) { 1591 A2dpService a2dpService = A2dpService.getA2dpService(); 1592 if ((a2dpService != null) && 1593 (BluetoothProfile.PRIORITY_AUTO_CONNECT != a2dpService.getPriority(device))){ 1594 adjustOtherSinkPriorities(a2dpService, device); 1595 a2dpService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT); 1596 } 1597 } 1598 } 1599 1600 boolean cancelBondProcess(BluetoothDevice device) { 1601 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1602 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1603 return cancelBondNative(addr); 1604 } 1605 1606 boolean removeBond(BluetoothDevice device) { 1607 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1608 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1609 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 1610 return false; 1611 } 1612 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 1613 msg.obj = device; 1614 mBondStateMachine.sendMessage(msg); 1615 return true; 1616 } 1617 1618 int getBondState(BluetoothDevice device) { 1619 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1620 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1621 if (deviceProp == null) { 1622 return BluetoothDevice.BOND_NONE; 1623 } 1624 return deviceProp.getBondState(); 1625 } 1626 1627 int getConnectionState(BluetoothDevice device) { 1628 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1629 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1630 return getConnectionStateNative(addr); 1631 } 1632 1633 String getRemoteName(BluetoothDevice device) { 1634 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1635 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1636 if (deviceProp == null) return null; 1637 return deviceProp.getName(); 1638 } 1639 1640 int getRemoteType(BluetoothDevice device) { 1641 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1642 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1643 if (deviceProp == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1644 return deviceProp.getDeviceType(); 1645 } 1646 1647 String getRemoteAlias(BluetoothDevice device) { 1648 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1649 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1650 if (deviceProp == null) return null; 1651 return deviceProp.getAlias(); 1652 } 1653 1654 boolean setRemoteAlias(BluetoothDevice device, String name) { 1655 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1656 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1657 if (deviceProp == null) return false; 1658 deviceProp.setAlias(device, name); 1659 return true; 1660 } 1661 1662 int getRemoteClass(BluetoothDevice device) { 1663 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1664 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1665 if (deviceProp == null) return 0; 1666 1667 return deviceProp.getBluetoothClass(); 1668 } 1669 1670 ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 1671 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1672 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1673 if (deviceProp == null) return null; 1674 return deviceProp.getUuids(); 1675 } 1676 1677 boolean fetchRemoteUuids(BluetoothDevice device) { 1678 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1679 mRemoteDevices.fetchUuids(device); 1680 return true; 1681 } 1682 1683 1684 boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 1685 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1686 "Need BLUETOOTH ADMIN permission"); 1687 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1688 // Only allow setting a pin in bonding state, or bonded state in case of security upgrade. 1689 if (deviceProp == null || 1690 (deviceProp.getBondState() != BluetoothDevice.BOND_BONDING && 1691 deviceProp.getBondState() != BluetoothDevice.BOND_BONDED)) { 1692 return false; 1693 } 1694 1695 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1696 return pinReplyNative(addr, accept, len, pinCode); 1697 } 1698 1699 boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 1700 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1701 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1702 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1703 return false; 1704 } 1705 1706 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1707 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept, 1708 Utils.byteArrayToInt(passkey)); 1709 } 1710 1711 boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 1712 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1713 "Need BLUETOOTH ADMIN permission"); 1714 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1715 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1716 return false; 1717 } 1718 1719 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1720 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 1721 accept, 0); 1722 } 1723 1724 int getPhonebookAccessPermission(BluetoothDevice device) { 1725 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1726 SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 1727 Context.MODE_PRIVATE); 1728 if (!pref.contains(device.getAddress())) { 1729 return BluetoothDevice.ACCESS_UNKNOWN; 1730 } 1731 return pref.getBoolean(device.getAddress(), false) 1732 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; 1733 } 1734 1735 boolean setPhonebookAccessPermission(BluetoothDevice device, int value) { 1736 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1737 "Need BLUETOOTH PRIVILEGED permission"); 1738 SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 1739 Context.MODE_PRIVATE); 1740 SharedPreferences.Editor editor = pref.edit(); 1741 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 1742 editor.remove(device.getAddress()); 1743 } else { 1744 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 1745 } 1746 return editor.commit(); 1747 } 1748 1749 int getMessageAccessPermission(BluetoothDevice device) { 1750 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1751 SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 1752 Context.MODE_PRIVATE); 1753 if (!pref.contains(device.getAddress())) { 1754 return BluetoothDevice.ACCESS_UNKNOWN; 1755 } 1756 return pref.getBoolean(device.getAddress(), false) 1757 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; 1758 } 1759 1760 boolean setMessageAccessPermission(BluetoothDevice device, int value) { 1761 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1762 "Need BLUETOOTH PRIVILEGED permission"); 1763 SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 1764 Context.MODE_PRIVATE); 1765 SharedPreferences.Editor editor = pref.edit(); 1766 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 1767 editor.remove(device.getAddress()); 1768 } else { 1769 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 1770 } 1771 return editor.commit(); 1772 } 1773 1774 int getSimAccessPermission(BluetoothDevice device) { 1775 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1776 SharedPreferences pref = getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, 1777 Context.MODE_PRIVATE); 1778 if (!pref.contains(device.getAddress())) { 1779 return BluetoothDevice.ACCESS_UNKNOWN; 1780 } 1781 return pref.getBoolean(device.getAddress(), false) 1782 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; 1783 } 1784 1785 boolean setSimAccessPermission(BluetoothDevice device, int value) { 1786 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1787 "Need BLUETOOTH PRIVILEGED permission"); 1788 SharedPreferences pref = getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, 1789 Context.MODE_PRIVATE); 1790 SharedPreferences.Editor editor = pref.edit(); 1791 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 1792 editor.remove(device.getAddress()); 1793 } else { 1794 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 1795 } 1796 return editor.commit(); 1797 } 1798 1799 void sendConnectionStateChange(BluetoothDevice 1800 device, int profile, int state, int prevState) { 1801 // TODO(BT) permission check? 1802 // Since this is a binder call check if Bluetooth is on still 1803 if (getState() == BluetoothAdapter.STATE_OFF) return; 1804 1805 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 1806 1807 } 1808 1809 ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 1810 ParcelUuid uuid, int port, int flag) { 1811 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1812 int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()), 1813 type, Utils.uuidToByteArray(uuid), port, flag); 1814 if (fd < 0) { 1815 errorLog("Failed to connect socket"); 1816 return null; 1817 } 1818 return ParcelFileDescriptor.adoptFd(fd); 1819 } 1820 1821 ParcelFileDescriptor createSocketChannel(int type, String serviceName, 1822 ParcelUuid uuid, int port, int flag) { 1823 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1824 int fd = createSocketChannelNative(type, serviceName, 1825 Utils.uuidToByteArray(uuid), port, flag); 1826 if (fd < 0) { 1827 errorLog("Failed to create socket channel"); 1828 return null; 1829 } 1830 return ParcelFileDescriptor.adoptFd(fd); 1831 } 1832 1833 boolean configHciSnoopLog(boolean enable) { 1834 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1835 return configHciSnoopLogNative(enable); 1836 } 1837 1838 boolean factoryReset() { 1839 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 1840 return factoryResetNative(); 1841 } 1842 1843 void registerCallback(IBluetoothCallback cb) { 1844 mCallbacks.register(cb); 1845 } 1846 1847 void unregisterCallback(IBluetoothCallback cb) { 1848 mCallbacks.unregister(cb); 1849 } 1850 1851 public int getNumOfAdvertisementInstancesSupported() { 1852 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1853 return mAdapterProperties.getNumOfAdvertisementInstancesSupported(); 1854 } 1855 1856 public boolean isMultiAdvertisementSupported() { 1857 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1858 return getNumOfAdvertisementInstancesSupported() >= MIN_ADVT_INSTANCES_FOR_MA; 1859 } 1860 1861 public boolean isRpaOffloadSupported() { 1862 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1863 return mAdapterProperties.isRpaOffloadSupported(); 1864 } 1865 1866 public int getNumOfOffloadedIrkSupported() { 1867 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1868 return mAdapterProperties.getNumOfOffloadedIrkSupported(); 1869 } 1870 1871 public int getNumOfOffloadedScanFilterSupported() { 1872 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1873 return mAdapterProperties.getNumOfOffloadedScanFilterSupported(); 1874 } 1875 1876 public boolean isPeripheralModeSupported() { 1877 return getResources().getBoolean(R.bool.config_bluetooth_le_peripheral_mode_supported); 1878 } 1879 1880 public int getOffloadedScanResultStorage() { 1881 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1882 return mAdapterProperties.getOffloadedScanResultStorage(); 1883 } 1884 1885 private boolean isActivityAndEnergyReportingSupported() { 1886 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 1887 return mAdapterProperties.isActivityAndEnergyReportingSupported(); 1888 } 1889 1890 private void getActivityEnergyInfoFromController() { 1891 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 1892 if (isActivityAndEnergyReportingSupported()) { 1893 readEnergyInfo(); 1894 } 1895 } 1896 1897 private BluetoothActivityEnergyInfo reportActivityInfo() { 1898 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 1899 BluetoothActivityEnergyInfo info = 1900 new BluetoothActivityEnergyInfo(SystemClock.elapsedRealtime(), mStackReportedState, 1901 mTxTimeTotalMs, mRxTimeTotalMs, mIdleTimeTotalMs, mEnergyUsedTotalVoltAmpSecMicro); 1902 // Read on clear values; a record of data is created with 1903 // timstamp and new samples are collected until read again 1904 mStackReportedState = 0; 1905 mTxTimeTotalMs = 0; 1906 mRxTimeTotalMs = 0; 1907 mIdleTimeTotalMs = 0; 1908 mEnergyUsedTotalVoltAmpSecMicro = 0; 1909 return info; 1910 } 1911 1912 public int getTotalNumOfTrackableAdvertisements() { 1913 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1914 return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); 1915 } 1916 1917 public void onLeServiceUp() { 1918 Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 1919 mAdapterStateMachine.sendMessage(m); 1920 } 1921 1922 public void onBrEdrDown() { 1923 Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 1924 mAdapterStateMachine.sendMessage(m); 1925 } 1926 1927 private static int convertScanModeToHal(int mode) { 1928 switch (mode) { 1929 case BluetoothAdapter.SCAN_MODE_NONE: 1930 return AbstractionLayer.BT_SCAN_MODE_NONE; 1931 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 1932 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 1933 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 1934 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1935 } 1936 // errorLog("Incorrect scan mode in convertScanModeToHal"); 1937 return -1; 1938 } 1939 1940 static int convertScanModeFromHal(int mode) { 1941 switch (mode) { 1942 case AbstractionLayer.BT_SCAN_MODE_NONE: 1943 return BluetoothAdapter.SCAN_MODE_NONE; 1944 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 1945 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 1946 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 1947 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1948 } 1949 //errorLog("Incorrect scan mode in convertScanModeFromHal"); 1950 return -1; 1951 } 1952 1953 // This function is called from JNI. It allows native code to set a single wake 1954 // alarm. If an alarm is already pending and a new request comes in, the alarm 1955 // will be rescheduled (i.e. the previously set alarm will be cancelled). 1956 private boolean setWakeAlarm(long delayMillis, boolean shouldWake) { 1957 synchronized (this) { 1958 if (mPendingAlarm != null) { 1959 mAlarmManager.cancel(mPendingAlarm); 1960 } 1961 1962 long wakeupTime = SystemClock.elapsedRealtime() + delayMillis; 1963 int type = shouldWake 1964 ? AlarmManager.ELAPSED_REALTIME_WAKEUP 1965 : AlarmManager.ELAPSED_REALTIME; 1966 1967 Intent intent = new Intent(ACTION_ALARM_WAKEUP); 1968 mPendingAlarm = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); 1969 mAlarmManager.setExact(type, wakeupTime, mPendingAlarm); 1970 return true; 1971 } 1972 } 1973 1974 // This function is called from JNI. It allows native code to acquire a single wake lock. 1975 // If the wake lock is already held, this function returns success. Although this function 1976 // only supports acquiring a single wake lock at a time right now, it will eventually be 1977 // extended to allow acquiring an arbitrary number of wake locks. The current interface 1978 // takes |lockName| as a parameter in anticipation of that implementation. 1979 private boolean acquireWakeLock(String lockName) { 1980 if (mWakeLock != null) { 1981 if (!lockName.equals(mWakeLockName)) { 1982 errorLog("Multiple wake lock acquisition attempted; aborting: " + lockName); 1983 return false; 1984 } 1985 1986 // We're already holding the desired wake lock so return success. 1987 if (mWakeLock.isHeld()) { 1988 return true; 1989 } 1990 } 1991 1992 mWakeLockName = lockName; 1993 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName); 1994 mWakeLock.acquire(); 1995 return true; 1996 } 1997 1998 // This function is called from JNI. It allows native code to release a wake lock acquired 1999 // by |acquireWakeLock|. If the wake lock is not held, this function returns failure. 2000 // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is 2001 // needed here. See the comment for |acquireWakeLock| for an explanation of the interface. 2002 private boolean releaseWakeLock(String lockName) { 2003 synchronized (this) { 2004 if (mWakeLock == null) { 2005 errorLog("Repeated wake lock release; aborting release: " + lockName); 2006 return false; 2007 } 2008 2009 mWakeLock.release(); 2010 mWakeLock = null; 2011 mWakeLockName = null; 2012 } 2013 return true; 2014 } 2015 2016 private void energyInfoCallback (int status, int ctrl_state, 2017 long tx_time, long rx_time, long idle_time, long energy_used) 2018 throws RemoteException { 2019 if (ctrl_state >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID && 2020 ctrl_state <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) { 2021 mStackReportedState = ctrl_state; 2022 mTxTimeTotalMs += tx_time; 2023 mRxTimeTotalMs += rx_time; 2024 mIdleTimeTotalMs += idle_time; 2025 // Energy is product of mA, V and ms. If the chipset doesn't 2026 // report it, we have to compute it from time 2027 if (energy_used == 0) { 2028 energy_used = (long)((mTxTimeTotalMs * getTxCurrentMa() 2029 + mRxTimeTotalMs * getRxCurrentMa() 2030 + mIdleTimeTotalMs * getIdleCurrentMa()) * getOperatingVolt()); 2031 } 2032 mEnergyUsedTotalVoltAmpSecMicro += energy_used; 2033 } 2034 2035 debugLog("energyInfoCallback() status = " + status + 2036 "tx_time = " + tx_time + "rx_time = " + rx_time + 2037 "idle_time = " + idle_time + "energy_used = " + energy_used + 2038 "ctrl_state = " + ctrl_state); 2039 } 2040 2041 private int getIdleCurrentMa() { 2042 return getResources().getInteger(R.integer.config_bluetooth_idle_cur_ma); 2043 } 2044 2045 private int getTxCurrentMa() { 2046 return getResources().getInteger(R.integer.config_bluetooth_tx_cur_ma); 2047 } 2048 2049 private int getRxCurrentMa() { 2050 return getResources().getInteger(R.integer.config_bluetooth_rx_cur_ma); 2051 } 2052 2053 private double getOperatingVolt() { 2054 return getResources().getInteger(R.integer.config_bluetooth_operating_voltage_mv) / 1000.0; 2055 } 2056 2057 private void dump(FileDescriptor fd) { 2058 // Collect profile information 2059 StringBuilder sb = new StringBuilder(); 2060 synchronized (mProfiles) { 2061 for (ProfileService profile : mProfiles) { 2062 profile.dump(sb); 2063 } 2064 } 2065 2066 // Dump Java based profiles first 2067 FileWriter fw = null; 2068 try { 2069 fw = new FileWriter(fd); 2070 fw.write(sb.toString()); 2071 } catch (IOException ex) { 2072 errorLog("IOException writing profile status!"); 2073 } finally { 2074 if (fw != null) { 2075 try { 2076 fw.close(); 2077 } catch (IOException ex) { 2078 debugLog("IOException closing a file after writing the profile status"); 2079 } 2080 } 2081 } 2082 2083 // Add native logs 2084 dumpNative(fd); 2085 } 2086 2087 private void debugLog(String msg) { 2088 if (DBG) Log.d(TAG, msg); 2089 } 2090 2091 private void errorLog(String msg) { 2092 Log.e(TAG, msg); 2093 } 2094 2095 private final BroadcastReceiver mAlarmBroadcastReceiver = new BroadcastReceiver() { 2096 @Override 2097 public void onReceive(Context context, Intent intent) { 2098 synchronized (AdapterService.this) { 2099 mPendingAlarm = null; 2100 alarmFiredNative(); 2101 } 2102 } 2103 }; 2104 2105 private native static void classInitNative(); 2106 private native boolean initNative(); 2107 private native void cleanupNative(); 2108 /*package*/ native boolean enableNative(); 2109 /*package*/ native boolean disableNative(); 2110 /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val); 2111 /*package*/ native boolean getAdapterPropertiesNative(); 2112 /*package*/ native boolean getAdapterPropertyNative(int type); 2113 /*package*/ native boolean setAdapterPropertyNative(int type); 2114 /*package*/ native boolean 2115 setDevicePropertyNative(byte[] address, int type, byte[] val); 2116 /*package*/ native boolean getDevicePropertyNative(byte[] address, int type); 2117 2118 /*package*/ native boolean createBondNative(byte[] address, int transport); 2119 /*package*/ native boolean removeBondNative(byte[] address); 2120 /*package*/ native boolean cancelBondNative(byte[] address); 2121 /*package*/ native boolean sdpSearchNative(byte[] address, byte[] uuid); 2122 2123 /*package*/ native int getConnectionStateNative(byte[] address); 2124 2125 private native boolean startDiscoveryNative(); 2126 private native boolean cancelDiscoveryNative(); 2127 2128 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 2129 private native boolean sspReplyNative(byte[] address, int type, boolean 2130 accept, int passkey); 2131 2132 /*package*/ native boolean getRemoteServicesNative(byte[] address); 2133 /*package*/ native boolean getRemoteMasInstancesNative(byte[] address); 2134 2135 private native int readEnergyInfo(); 2136 // TODO(BT) move this to ../btsock dir 2137 private native int connectSocketNative(byte[] address, int type, 2138 byte[] uuid, int port, int flag); 2139 private native int createSocketChannelNative(int type, String serviceName, 2140 byte[] uuid, int port, int flag); 2141 2142 /*package*/ native boolean configHciSnoopLogNative(boolean enable); 2143 /*package*/ native boolean factoryResetNative(); 2144 2145 private native void alarmFiredNative(); 2146 private native void dumpNative(FileDescriptor fd); 2147 2148 protected void finalize() { 2149 cleanup(); 2150 if (TRACE_REF) { 2151 synchronized (AdapterService.class) { 2152 sRefCount--; 2153 debugLog("finalize() - REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount); 2154 } 2155 } 2156 } 2157} 2158