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