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