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